Friday, 4 July 2014

Tooltip Data Annotation

I am a fan of Data Annotations, I like the fact I can define stuff in one place and it works everywhere.
One thing I felt that was missing is a tooltip annotation, which then using the technique discussed in “Standardising through HTML helpers

Coding the Data Annotation

The Data Annotation is going to look like this
   [StringLength(255)]
   [DisplayName("Colour")]
   [ToolTip("This is the colour used in the Project Management Page,
 please use html colours.")]
   public string PriorityColour { getset; }
To create the data annotation is simple and documented here, but this is the code.

 public class ToolTipAttribute : DescriptionAttribute

 {
     public ToolTipAttribute()
         : base("")
     {

     }

     public ToolTipAttribute(string description)
         : base(description)
     {

     }
 }

Adding the Data Annotation to myTextboxFor

Depending on your JS control set of choice you may need to amend this slightly. I am using Bootstrap.
The first step is getting the tooltip from the Data Annotation, to do this we are going to get all of the Member Expressions from the Model.
As I have a number of different myxxxFor, I do this in a separate function. which is relatively simple, it is a case of iterating through the MemberExpressions until you find the tooltip and then returning the string.
private static string GetToolTipFromAnnotation(MemberExpression memberExpression)
   {
       string toolTip = "";

       foreach (Attribute attribute in memberExpression.Expression.Type 
.GetProperty(memberExpression.Member.Name).GetCustomAttributes(false))
       {
           if (typeof(ToolTipAttribute== attribute.GetType())
           {
               toolTip = ((ToolTipAttribute)attribute).Description;
           }
       }

       return toolTip;
   }

Calling this code from the MyTextBoxFor code is
string toolTip = GetToolTipFromAnnotation((MemberExpression)expression.Body);

Then we need to add some additional classes to our input class, 
in the last blog we had MyTextboxFor returning this.
return helper.TextBoxFor(expression, formatString, new { @class = additionalClass});

To include the tooltip we need a bit more.
return helper.TextBoxFor(expression, formatString, new {@class = additionalClass 
" tooltipHolder"@data_toggle = "tooltip"@data_content = toolTip});

Then on your page call the popover (or tooltip, I use popover as 
I prefer the look and feel.)
$(".tooltipHolder").popover({ trigger'hover' });
As usual the code is examples and may need more or less work for you but 
I hope it helps.

Friday, 27 June 2014

Standardising through HTML Helpers

HTML TextBoxFor in Razor are really useful.


I know that is a bit of an understatement,but they can be even better.  I use bootstrap (www.getbootstrap.com) and a number of other js components such as the bootstrap date picker( http://www.eyecon.ro/bootstrap-datepicker/ ) .  And by creating my own versions of the helpers we can add a lot of conformity and standardisation.  Also if we want to change the control it is in a central place!



Creating our own helper.

The helper needs to be static and return an MvcHtmlString .

The new helper is going to be called MyTextBoxFor and will be called in the same way as the original helper, like so.

 @Html.MyTextBoxFor( model => model.Name)

For Bootstrap we need to include a class I use "form-control" normally using Razor, we would need to add a class element such as;

@Html.TextBoxFor(model => model.Name, new {@class = "form-control"}) 

so for our helper we are going to include this.


 public static MvcHtmlString MyTextBoxFor(this HtmlHelper helper, Expression> expression, bool addReadonly = false)
    { 
      var additionalClass = "form-control";
      var formatString = string.Empty;
      return helper.TextBoxFor(expression, formatString, new { @class = additionalClass});
    }

Already we are starting to save ourselves some effort, now we can get away with just calling the first snippet rather than the 2nd.

The astute of you will notice the formatString variable in the class, what is that for?  As mentioned earlier I use JS components, we can start to plug some of these in.

Expression> allows us to access information about the property we are building the control, in particular Body.Type gets us the data type.

the next step is to do a quick query on this and we can start to add some more information

this time we are going to add the datePicker class and a format String ( I like my dates to display like 25-Dec-2015)



  public static MvcHtmlString MyTextBoxFor(this HtmlHelper helper, Expression> expression, bool addReadonly = false)
    {
        string additionalClass = "form-control";
        

        // add datepicker class to date data types/
        Type dataType = expression.Body.Type;
        var formatString = string.Empty;

       
        if (dataType == typeof(DateTime) || dataType == typeof(DateTime?))
        {
            additionalClass = "datePicker form-control";
            formatString = "{0:dd-MMM-yyyy}";
        }
              
        return helper.TextBoxFor(expression, formatString, new { @class = additionalClass});
    }

And that is about all there is to it, there is obviously much more you can do, for example Read Only is almost plugged in. You could do spinners for numbers etc.

I hope this helps and enjoy.

Update 
I have just added a new blog which uses this technique to display tooltips please see here http://cursethecompiler.blogspot.co.uk/2014/07/tooltip-data-annotation.html