Explain Codes LogoExplain Codes Logo

Html5 Placeholders with .NET MVC 3 Razor EditorFor extension?

html
prompt-engineering
editor-for
mvc-templates
Nikita BarsukovbyNikita Barsukov·Dec 22, 2024
TLDR

Implementing placeholders in Razor can be easily performed by swapping EditorFor for TextBoxFor. Just remember to add a placeholder attribute:

@Html.TextBoxFor(m => m.Property, new { placeholder = "Enter text" })

This line of code generates an input box with placeholder text, immediately connecting to your model's Property.

Placeholder Text with ModelMetadata

If you're eying a more MVC-centric approach, consider using ModelMetadata. Add a [Display(Prompt = "Fill in your text here")] decoration to your ViewModel properties, essentially commanding MVC to do the heavy lifting:

public class ViewModelForChampions { [Display(Prompt = "Enter your name")] public string Name { get; set; } // Your name's not null or empty, right? }

Then in Views/Shared/EditorTemplates/String.cshtml, customize your string template with a neat line of ViewData.ModelMetadata.Watermark:

@model string <input class="text-box single-line" type="text" placeholder="@ViewData.ModelMetadata.Watermark" value="@Model" /> <!-- No model? No problem. Or is it? -->

After setting this up, @Html.EditorFor(m => m.Name) honors the placeholder text you defined in your model.

Crafting Custom HtmlHelper Extensions

When placeholders are your bread and butter and you're more inclined towards stickiness with EditorFor, take the custom route by writing an HtmlHelper extension method:

public static MvcHtmlString EditorForButBetter<TModel, TValue>( this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) { var md = ModelMetadata.FromLambdaExpression(expression, html.ViewData); //md, because who likes typing? return html.TextBoxFor(expression, new { placeholder = md.Watermark }); //md, not a doctor, but still important! }

Execute it as you would a standard EditorFor:

@Html.EditorForButBetter(m => m.Property) //Because sometimes, regular EditorFor doesn't cut it.

Reacting Dynamically with Placeholders

Sometimes, placeholders need to have the ability to adapt to runtime changes. Use ViewData to assign the placeholder text right when your view is generated:

@Html.TextBoxFor(m => m.Property, new { placeholder = ViewData["DynamicPlaceholder"] })

In your controller action, activate this feature by setting ViewData:

ViewData["DynamicPlaceholder"] = "Text dependent on conditions"; //Conditions: The web dev's weather forecast

Placeholders with Multilingual Support

To accomplish multilingual support for your placeholders, apply Resource files and meld them with DisplayAttribute:

[Display(Prompt = nameof(Resources.PlaceholderText))] public string GlobalProperty { get; set; } // Loves to travel and meet new languages

Configure your DataAnnotationsModelMetadataProvider for this function to play well with resource files.

Autofocusing First Input

Improve user experience by enabling autofocus on the first input box. Build a fresh HtmlHelper extension for autofocus:

public static MvcHtmlString EditorForWithFocus<TModel, TValue>( this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) { var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); // New superhero: Metadatum return html.TextBoxFor(expression, new { placeholder = metadata.Watermark, autofocus = "autofocus" }); // Blink, and you'll miss it! }

To auto-focus on a certain field at the beginning, code it like so:

@Html.EditorForWithFocus(m => m.PrimaryInputField) //Standing at attention!

Rickrolling with MVC Templates

Go nuclear by modifying the MVC default templates to include the placeholder attribute. This isn't for the faint-hearted, but once done, each time you use EditorFor for strings, it'll pick up the behavior coded into the template:

@model string @{ var watermark = ViewData.ModelMetadata.Watermark; //Water(wall)mark } <input type="text" placeholder="@watermark" value="@Model" /> //I'm a placeholder, not a water bottle

Get this snippet placed in your Views/Shared/EditorTemplates/String.cshtml file, and watch the magic happen.