.NET MVC 3 Razor 편집기를 사용하는 HTML5 자리 표시 자


92

@ Html.EditorFor를 사용하여 Html5 자리 표시자를 작성하는 방법이 있습니까 , 아니면 TextBoxFor 확장을 사용해야합니까?

@Html.TextBoxFor(model => model.Title, new { @placeholder = "Enter title here"})

또는 DataAnnotations를 통해 'Description'표시 속성을 사용할 수있는 자체 사용자 지정 확장을 작성하는 것이 합리적 일까요 ( this 와 유사 )?

물론 동일한 질문이 '자동 초점'에도 적용됩니다.

답변:


68

사용자 정의 작성 에 대한 다음 기사 를 살펴볼 수 있습니다 DataAnnotationsModelMetadataProvider.

그리고 새로 도입 된 IMetadataAware 인터페이스를 포함하여 진행하는 또 다른 ASP.NET MVC 3ish 방법이 있습니다.

이 인터페이스를 구현하는 사용자 정의 속성을 작성하여 시작하십시오.

public class PlaceHolderAttribute : Attribute, IMetadataAware
{
    private readonly string _placeholder;
    public PlaceHolderAttribute(string placeholder)
    {
        _placeholder = placeholder;
    }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["placeholder"] = _placeholder;
    }
}

그런 다음 모델을 장식합니다.

public class MyViewModel
{
    [PlaceHolder("Enter title here")]
    public string Title { get; set; }
}

다음으로 컨트롤러를 정의합니다.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }
}

해당보기 :

@model MyViewModel
@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.Title)
    <input type="submit" value="OK" />
}

마지막으로 편집기 템플릿 ( ~/Views/Shared/EditorTemplates/string.cshtml) :

@{
    var placeholder = string.Empty;
    if (ViewData.ModelMetadata.AdditionalValues.ContainsKey("placeholder"))
    {
        placeholder = ViewData.ModelMetadata.AdditionalValues["placeholder"] as string;
    }
}
<span>
    @Html.Label(ViewData.ModelMetadata.PropertyName)
    @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { placeholder = placeholder })
</span>

IMetadataAware 인터페이스의 정보 (그리고 훌륭한 예)에 감사드립니다!
seekay 2011

4
MVC3에 여전히 유효합니까? MVC3에서 새로운 [Display (Prompt = "type watermark here")]를 발견했지만 작동하지 못했습니다. 어떤 생각?
smnbss 2011-06-16

2
@smnbss 당신이 맞습니다. Prompt일하는 방법을 보려면 내 대답을 참조하십시오 .
Daniel Liuzzi

6
자리 표시자를 만드는 데 그렇게 많은 작업이 필요합니까? 더 간단한 것이
어야합니다

아래에 몇 가지 답변이 있습니다. Pax는 좋은 것을 가지고 있습니다.
Termato

121

Darin Dimitrov의 답변에 smnbss가 언급했듯이 Prompt 정확히이 목적을 위해 존재하므로 사용자 지정 속성을 만들 필요없습니다 . 문서에서 :

UI의 프롬프트에 대한 워터 마크를 설정하는 데 사용할 값을 가져 오거나 설정합니다.

그것을 사용하려면 다음과 같이 뷰 모델의 속성을 장식하십시오.

[Display(Prompt = "numbers only")]
public int Age { get; set; }

이 텍스트는에 편리하게 배치됩니다 ModelMetadata.Watermark. 기본적으로 MVC 3의 기본 템플릿은Watermark 속성을 하지만 작동하는 것은 정말 간단합니다. MVC에 렌더링 방법을 알려주기 위해 기본 문자열 템플릿을 수정하기 만하면됩니다. Darin처럼 String.cshtml을 편집하십시오. 단,에서 워터 마크를 가져 오는 대신 다음에서 ModelMetadata.AdditionalValues바로 가져옵니다 ModelMetadata.Watermark.

~ / Views / Shared / EditorTemplates / String.cshtml :

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", placeholder = ViewData.ModelMetadata.Watermark })

그리고 그게 다입니다.

보시다시피 모든 것을 작동시키는 핵심은 placeholder = ViewData.ModelMetadata.Watermark 비트입니다.

여러 줄 텍스트 상자 (텍스트 영역)에 대해 워터 마크를 활성화하려면 MultilineText.cshtml에 대해서도 동일한 작업을 수행합니다.

~ / Views / Shared / EditorTemplates / MultilineText.cshtml :

@Html.TextArea("", ViewData.TemplateInfo.FormattedModelValue.ToString(), 0, 0, new { @class = "text-box multi-line", placeholder = ViewData.ModelMetadata.Watermark })

6
@Brett 실제로 있습니다. EditorFor ()는 MVC 2에 도입 된 템플릿 도우미입니다. 언뜻보기에는 TextBox ()와 동일한 작업을 수행하는 것처럼 보이지만 HTML 생성 방법을 정확하게 제어 할 수있는 큰 이점을 제공합니다. 내 대답은이 기능을 기반으로 MVC에 Prompt속성 으로 수행 할 작업을 "교육" 합니다. 이러한 템플릿에 대한 자세한 내용은 Brad Wilson의 훌륭한 게시물 bradwilson.typepad.com/blog/2009/10/…을
Daniel Liuzzi

2
@DotNetWise 나는 당신이 왜 그렇게 말하는지 잘 모르겠습니다. DisplayAttribute(프롬프트 포함) 의 모든 문자열 매개 변수 는 지역화 할 수 있습니다. 주석에 ResourceType을 지정하기 만하면 [Display(ResourceType = typeof(PeopleResources), Prompt = "AgePrompt")]됩니다.. 그리고 그게 다야. 워터 마크 텍스트는 이제 PeopleResources 리소스의 키 AgeGroup 에서 가져옵니다 .
Daniel Liuzzi

1
.resx 리소스를 사용하지 않고 i18N .po 현지화 시스템을 사용하는 경우 어떻게됩니까?
Adaptabi 2012

3
@FrancisRodgers EditorTemplates폴더는 기본적으로 없습니다. Views\Shared폴더에 생성하기 만하면됩니다 (또는 Views\{ControllerName}특정 컨트롤러에만 적용되도록하려면). 그런 다음 .cshtml 템플릿을이 폴더 안에 넣으면 잘 될 것입니다.
Daniel Liuzzi 2013-02-05

2
@RobertIvanc 나는 대답을 편집하고 당신과 Ted 가보고 한 문제를 일으키는 Raleigh Buckner의 편집을 되돌 렸습니다. 감사.
Daniel Liuzzi

22

실제로 대부분의 경우 자리 표시 자 텍스트에 표시 이름을 사용하는 것을 선호합니다. 다음은 DisplayName을 사용하는 예입니다.

  @Html.TextBoxFor(x => x.FirstName, true, null, new { @class = "form-control", placeholder = Html.DisplayNameFor(x => x.FirstName) })

1
워터 마크에 대한 특수 데이터 주석 프롬프트가 있습니다. 그리고 DisplayName은 필드 레이블 용입니다. 그것들을 혼합하는 것은 나쁜 생각입니다. 올바른 작업에 올바른 것을 사용하십시오. 내 대답을보세요.
Mike Eshva 2014 년

1
내가 왜 더 클래스 추가 단순 위해 우리는 다음 표시 이름을 얻을 수있는 지점을 찾고 있었는지의 감사
saqibahmad

이것은 DisplayName에서 제공하는 텍스트를 이중 이스케이프 처리합니다. 예를 들어 프랑스어와 같은 악센트가있는 언어의 경우 좋은 솔루션이 아닙니다.
marapet

3

다음과 같은 간단한 클래스를 작성했습니다.

public static class WatermarkExtension
{
    public static MvcHtmlString WatermarkFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        var watermark = ModelMetadata.FromLambdaExpression(expression, html.ViewData).Watermark;
        var htmlEncoded = HttpUtility.HtmlEncode(watermark);
        return new MvcHtmlString(htmlEncoded);
    }
}

다음과 같은 사용법 :

@Html.TextBoxFor(model => model.AddressSuffix, new {placeholder = Html.WatermarkFor(model => model.AddressSuffix)})

뷰 모델의 속성 :

[Display(ResourceType = typeof (Resources), Name = "AddressSuffixLabel", Prompt = "AddressSuffixPlaceholder")]
public string AddressSuffix
{
    get { return _album.AddressSuffix; }
    set { _album.AddressSuffix = value; }
}

알림 프롬프트 매개 변수. 이 경우 지역화를 위해 리소스의 문자열을 사용하지만 문자열 만 사용할 수 있으며 ResourceType 매개 변수는 피하십시오.


DisplayNameFor 메서드를 디 컴파일하고 워터 마크에 대한 아날로그를 만들었습니다.
Mike Eshva 2014 년

안녕하세요, Display-> Prompt 값이 지정되지 않은 경우 DisplayName 속성 값을 사용하도록 MvcHtmlString WatermarkFor () 메서드를 변경할 수 있습니까?
Sasa Tancev

설명한대로 사용할 수 있도록 WatermarkExtension 클래스를 어디에 저장합니까? Html.WatermarkFor (모델 => model.AddressSuffix)
크레이그 Gjerdingen

3

나는 리소스 파일과 함께 이런 식으로 사용합니다 (더 이상 프롬프트가 필요하지 않습니다!)

@Html.TextBoxFor(m => m.Name, new 
{
     @class = "form-control",
     placeholder = @Html.DisplayName(@Resource.PleaseTypeName),
     autofocus = "autofocus",
     required = "required"
})

1

다음은 TextBoxFor 및 PasswordFor에 사용할 수있는 위의 아이디어를 사용하여 만든 솔루션입니다.

public static class HtmlHelperEx
{
    public static MvcHtmlString TextBoxWithPlaceholderFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        return htmlHelper.TextBoxFor(expression, htmlAttributes.AddAttribute("placeholder", metadata.Watermark));

    }

    public static MvcHtmlString PasswordWithPlaceholderFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        return htmlHelper.PasswordFor(expression, htmlAttributes.AddAttribute("placeholder", metadata.Watermark));

    }
}

public static class HtmlAttributesHelper
{
    public static IDictionary<string, object> AddAttribute(this object htmlAttributes, string name, object value)
    {
        var dictionary = htmlAttributes == null ? new Dictionary<string, object>() : htmlAttributes.ToDictionary();
        if (!String.IsNullOrWhiteSpace(name) && value != null && !String.IsNullOrWhiteSpace(value.ToString()))
            dictionary.Add(name, value);
        return dictionary;
    }

    public static IDictionary<string, object> ToDictionary(this object obj)
    {
        return TypeDescriptor.GetProperties(obj)
            .Cast<PropertyDescriptor>()
            .ToDictionary(property => property.Name, property => property.GetValue(obj));
    }
}

0

사용자 정의 EditorTemplate을 만드는 것은 좋은 해결책이 아니라고 생각합니다. 문자열, 숫자, 콤보 상자 등과 같은 다양한 경우에 대해 가능한 많은 tepmlates에 관심이 필요하기 때문입니다. 다른 솔루션은 HtmlHelper에 대한 사용자 지정 확장입니다.

모델:

public class MyViewModel
{
    [PlaceHolder("Enter title here")]
    public string Title { get; set; }
}

HTML 도우미 확장 :

   public static MvcHtmlString BsEditorFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TValue>> expression, string htmlClass = "")
{
    var modelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    var metadata = modelMetadata;

    var viewData = new
    {
        HtmlAttributes = new
            {
                @class = htmlClass,
                placeholder = metadata.Watermark,
            }
    };
    return htmlHelper.EditorFor(expression, viewData);

}

해당보기 :

@Html.BsEditorFor(x => x.Title)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.