New to me but solved an issue - Templated Helpers

Building and Modifying Razor Display Helpers 

Note: this post uses Microsoft C# only (as most of mine will). I'm using Visual Studio 2017 with C# 7.

I have created quite a few Html Helpers and they come in very handy. These are the C# static method kind such as the following which performs some rudimentary formatting of an address:

/// <summary>
/// Creates HTML for an Address section.
/// </summary>
/// <param name="htmlHelper" />
/// <param name="address" />The Address object to create the HTML for.
/// <param name="refTypes" />An IEnumerable list of reference types
 /// (used to parse the name of the address state).
/// <returns>Formatted HTML representing the Address object.</returns>
public static IHtmlString AddressInfoFor(
    this HtmlHelper htmlHelper,
    IAddress address,
    IEnumerable<IReferencetype> refTypes )
{
    var state = UIHelpers.GetStateName( address.StateID, refTypes );
    var tag = new StringBuilder( address.AddressType.GetDisplayName() );
    tag.Append( "" );
    tag.Append( "Address 1: " + address.Address1 );
    tag.Append( "" );
    tag.Append( "Address 2: " + address.Address2 );
    tag.Append( "" );
    tag.Append( "City, State, Zip: "
                + address.City
                + " " + state + " "
                + address.ZipCode );
    if( address.ZipPlusFour.Length > 0 )
        tag.Append( "-" + address.ZipPlusFour );
    tag.Append( "" );
    return new HtmlString( tag.ToString() );
}

Today, however, I found out about the Templated Helpers. I can't find a lot of info about them from Microsoft but there's info available from other sources which I'll list at the bottom of this post.

What is a Templated Helper and why should I care?


Yeah, that's probably what you're saying. In my case the issue was that I had been using an @Html.DisplayFor to display a boolean value. The boolean display helper for a boolean will show a disabled checkbox that is checked if the boolean value is true, and un-checked if the boolean value is false. That makes sense and is what you would expect. No problem.

Then I decided to modify my object to match my database which stores the value in a nullable column. As soon as I did that my UI showed a disabled drop-down with either "Not Set", "True", or "False", depending on the boolean value (or lack of value). I didn't like that display so I set out to see how to make it more to my liking.

I wanted to continue to display the disabled check box if the boolean was set. I wanted to display "(not set)" if the boolean was null. How do you do that without writing a method somewhere and then calling it differently than the @Html.DisplayFor call. It turns out there's an easy way. I keep hearing that MVC is pretty much completely open source and extensible and if you need to do something there is a way. So here's what I found...

The @Html.DisplayFor use coded templates to determine how to display the value for a particular property. And you can over-ride these templates. You don't do it with C# code, you just do it with some html using a Templated Helper.

You can control the scope of the helper by the location you pur the file. I wanted this new functionality to be global so I put in the ~/Views/Shared folder.

I created new folders called "DisplayTemplates" and "EditorTemplates". If you only want the helper to be applied to a certain folder you can place the helper file in the desired folder. (I haven't tried this personally).

The DisplayTemplates are used by the @Html.DisplayFor operation. I haven't found the Microsoft documentation that describes this but I'm assuming that either the MVC framework is looking for a DisplayTemplates folder (doubtful because it's not required - you can put the file anywhere) or it's simply looking for a match for the data type (bool? in this case).

However it's working under the hood, what happens is that the contents of your new file is used to render the UI for the control.

How do I take advantage of this wonderful gift?


In your template file, Boolean.cshtml in my case, you declare the data type you want to write the helper for. I wanted to handle the nullable boolean, so my data type is @model bool?. Then you write the display markup for the (in this case) 3 value options, true, false, null.

Here's the contents of my Boolean.cshtml file:

@model bool?

@if( Model.HasValue )
{
    // The bool has a value so display a disabled checkbox.
    <input class="check-box" disabled="disabled" type="checkbox" @(Model.Value ? "checked='checked'" : "") />
}
else
{
    // The bool does not have a value so display a message.
    <span class="font-de-emphasized">N/A</span>
}

Update 6/6/2017 - I modified my template to what you see above. I decided I didn't like the "(Not Set)" in my application. It seemed like it could be a mistake that the item wasn't set and in my case the value is either required or not, based on other form entries. When it isn't required, it is disabled and can't be entered by the user - the field is not applicable. I also wrapped the value in a span tag and render it with a class that uses a gray font-color to make it even more unobtrusive.

So far it does exactly what I wanted! Enjoy!

References:

Here are some references I found useful:
  1. Basic format for the file: https://stackoverflow.com/questions/9815344/changing-html-displayfor-boolean-checkbox-mvc
  2. Fix for file naming: https://stackoverflow.com/questions/5783505/using-razor-how-do-i-make-all-bool-properties-appear-as-yes-no-not-set-on-de 
  3. Additional info: http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html
  4. Walkthrough: Using Templated Helpers to Display Data in ASP.NET MVC:  https://msdn.microsoft.com/en-us/library/ee308450%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
  5. Official “How to” for MVC Editor/Display Templates?    https://stackoverflow.com/questions/12644640/official-how-to-for-mvc-editor-display-templates

Comments

Popular posts from this blog

A better mouse trap - issues with a Logitech Wireless Marathon Mouse M705

Implementing IDisposable Properly

Driver Training - cleaning up unused USB drivers