MVC Data Annotations And HtmlHelpers For KnockoutJS

In this article, I will show you how to create data annotations for MVC models and combine that with HtmlHelpers to render all attributes of KnockoutJS in input fields.

KnockoutJS is a JavaScript plugin with Model-View-View-Model (MVVM) pattern. When your data model's state changes, your UI updates automatically. Like AngularJS, it provides full control for a View and its Model.
 
In MVC, there are a lot of Data Annotations to use in our Models. The goal here is to create custom ones for KnockoutJS.
 
Let's get started!
 
What do we need?
  1. MVC application.

  2. DataBind Attribute classes for those KnockoutJS annotations.

    1. EnableDataBind: enables or disables a field.
    2. MaskDataBind: input masks for a field.
    3. DateDataBind: transforms an input into a date mask field.
    4. OptionsDataBind: configures a select field with options.

  3. HtmlHelper to render an input with those annotations.

    1. InputFor: renders an input for KnockoutJS.
    2. SelectFor: renders a select for KnockoutJS. 
The front-end 
 
 
All the fields above are "handled" by KnockoutJS. I have configured some data annotations for Person Model, as shown below.
 
Models/Person.cs 
  1. public sealed class Person  
  2.     {  
  3.         [Display(Name = "Name")]  
  4.         [Required]  
  5.         [ValueDataBind("person.Name")]  
  6.         [CssClassTag("form-control")]  
  7.         public string Name { getset; }  
  8.   
  9.         [ValueDataBind("person.Id")]  
  10.         public string Id { getset; }  
  11.   
  12.         [Display(Name = "Email")]  
  13.         [Required]  
  14.         [EmailAddress]  
  15.         [EnableDataBind("isEnableToEdit")]  
  16.         [ValueDataBind("person.Email")]  
  17.         [CssClassTag("form-control")]  
  18.         public string Email { getset; }  
  19.   
  20.         [Display(Name = "Bith Date")]  
  21.         [DateDataBind("person.BithDate")]  
  22.         [CssClassTag("form-control")]  
  23.         public DateTime? BithDate { getset; }  
  24.   
  25.         [Display(Name = "Gender")]  
  26.         [EnableDataBind("isEnableToEdit")]  
  27.         [OptionsDataBind("genders""person.Gender")]  
  28.         [CssClassTag("form-control")]  
  29.         public int? Gender { getset; }  
  30.     }  
In HTML, the code will be something like this.
 
Views/Person/Index.cshtml 
  1. @Html.InputFor(x => x.Person.Name)  
  2. @Html.InputFor(x => x.Person.BithDate)  
  3. @Html.SelectFor(x => x.Person.Gender)  
  4. @Html.InputFor(x => x.Person.Email)  
It will render the following.
  1. <input class="text-box single-line, form-control" data-val="true" data-val-required="The field Name is required." id="Person_Name" name="Person.Name" type="text" value="" data-bind="value: person.Name">  
  2.   
  3. <input class="text-box single-line, form-control" data-val="true" data-val-date="The field Bith Date must be a date." id="Person_BithDate" name="Person.BithDate" type="text" value="" data-bind="value: person.BithDate, dateValue: person.BithDate, mask: { mascara: '99/99/9999', tipo: 'Date', value: person.BithDate }">  
  4.   
  5. <select id="Person_Gender" name="Person.Gender" data-bind="enable: isEnableToEdit, options: genders, optionsText: 'Name', optionsValue:'Id', value: person.Gender" class="form-control"></select>  
  6.   
  7. <input class="text-box single-line, form-control" data-val="true" data-val-email="O campo Email não é um endereço de email válido." data-val-required="The field Email is required" id="Person_Email" name="Person.Email" type="email" value="" data-bind="enable: isEnableToEdit, value: person.Email">  
The JavaScript file is shown below. It is used to control some data in KnockoutJS for the front-end. The "isEnableToEdit" computed function is used to enable DataBind annotation in MVC Person Model.
 
Scripts/view-models/person.js 
  1. var personViewModel = function () {  
  2.   
  3.     var _vm = null,  
  4.   
  5.     createComputed = function () {  
  6.         _vm.isEnableToEdit = ko.computed(function () {  
  7.             return (_vm.person.Name() || '').length > 2;  
  8.         }, _vm);  
  9.     },  
  10.   
  11.     init = function (model) {  
  12.         _vm = {  
  13.             person: ko.mapping.fromJS(model.Person),  
  14.             genders: [  
  15.                 { Id: 0, Name: 'Select...' },  
  16.                 { Id: 1, Name: 'Masc' },  
  17.                 { Id: 2, Name: 'Fem' }  
  18.             ]  
  19.         };  
  20.   
  21.         createComputed();  
  22.   
  23.         var ctx = $('#person').get(0);  
  24.         ko.applyBindings(_vm, ctx);  
  25.     }  
  26.   
  27.     return {  
  28.         init: init  
  29.     }  
  30.   
  31. }();  
Download the full source code from the below link.

FSL.MvcDataAnnotationsHtmlHelpersKnockoutJS
 
Remark

I will update that repository with new annotations and HTML Helpers features.