Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Html5 Placeholders with .NET MVC 3 Razor EditorFor extension?

Is there a way to write the Html5 placeholder using @Html.EditorFor, or should I just use the TextBoxFor extension i.e.

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

Or would it make sense to write our own custom extension that can maybe use the 'Description' display attribute via DataAnnotations (similar to this)?

Of course, then the same question applies to 'autofocus' as well.

like image 769
seekay Avatar asked Apr 28 '11 19:04

seekay


People also ask

What is HTML EditorFor in MVC?

ASP.NET MVC includes the method that generates HTML input elements based on the datatype. The Html. Editor() or Html. EditorFor() extension methods generate HTML elements based on the data type of the model object's property.

What is difference between EditorFor and TextBoxFor in MVC?

Show activity on this post. TextBoxFor: It will render like text input html element corresponding to specified expression. In simple word it will always render like an input textbox irrespective datatype of the property which is getting bind with the control. EditorFor: This control is bit smart.

How do I use TextBoxFor in HTML?

The HtmlHelper class includes two extension methods TextBox() and TextBoxFor<TModel, TProperty>() that renders the HTML textbox control <input type="text"> in the razor view. It is recommended to use the generic TextBoxFor<TModel, TProperty>() method, which is less error prons and performs fast.


2 Answers

As smnbss comments in Darin Dimitrov's answer, Prompt exists for exactly this purpose, so there is no need to create a custom attribute. From the the documentation:

Gets or sets a value that will be used to set the watermark for prompts in the UI.

To use it, just decorate your view model's property like so:

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

This text is then conveniently placed in ModelMetadata.Watermark. Out of the box, the default template in MVC 3 ignores the Watermark property, but making it work is really simple. All you need to do is tweaking the default string template, to tell MVC how to render it. Just edit String.cshtml, like Darin does, except that rather than getting the watermark from ModelMetadata.AdditionalValues, you get it straight from ModelMetadata.Watermark:

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

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

And that is it.

As you can see, the key to make everything work is the placeholder = ViewData.ModelMetadata.Watermark bit.

If you also want to enable watermarking for multi-line textboxes (textareas), you do the same for 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 }) 
like image 179
Daniel Liuzzi Avatar answered Sep 29 '22 18:09

Daniel Liuzzi


You may take a look at the following article for writing a custom DataAnnotationsModelMetadataProvider.

And here's another, more ASP.NET MVC 3ish way to proceed involving the newly introduced IMetadataAware interface.

Start by creating a custom attribute implementing this interface:

public class PlaceHolderAttribute : Attribute, IMetadataAware {     private readonly string _placeholder;     public PlaceHolderAttribute(string placeholder)     {         _placeholder = placeholder;     }      public void OnMetadataCreated(ModelMetadata metadata)     {         metadata.AdditionalValues["placeholder"] = _placeholder;     } } 

And then decorate your model with it:

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

Next define a controller:

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

A corresponding view:

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

And finally the editor template (~/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> 
like image 25
Darin Dimitrov Avatar answered Sep 29 '22 17:09

Darin Dimitrov