Data Annotations e HtmlHelpers de MVC para KnockoutJS

Disponível também em inglês

Nesse artigo irei mostrar como criar data annotations para usar nas model do MVC e combinar o HtmlHelpers para renderizar as tags e atributos do KnockoutJS.

Atualizações:
Fev – 2017
– ValueDataBind – Opção para configurar quando o textbox atualizará a model.
Dez – 2016
– DoubleDataBind – Para uso de campos Double e Moeda.
– NoDataValTag – Adiciona um atributo data-val=”false”.

 
Data Annotations e HtmlHelpers de MVC para KnockoutJS
 


 

KnockoutJS é um plugin javascript para trabalhar com design pattern Model-View-View-Model (MVVM). Quando a model muda, toda a interface muda automaticamente. Assim como AngularJS ele possibilita o controle total do estado e mudanças na view e na model.

No MVC existem diversos Data Annotations para usar nas models. O objetivo aqui é criar alguns customizados para trabalhar com o KnockoutJS.

Vamos começar!

O que precisamos?

1 – aplicação MVC.
2 – Annotations para criar o atributo DataBind para o KnockoutJS.
2.1 – EnableDataBind: habilita ou desabilita um campo.
2.2 – MaskDataBind: máscara para os campos.
2.3 – DateDataBind: transforma um input em um campo com máscara de data.
2.4 – OptionsDataBind: configura as opções de um dropdownlist.
3 – HtmlHelper para renderizar os campos com esses data annotations.
3.1 – InputFor: Renderiza um input para KnockoutJS.
3.2 – SelectFor: Renderiza um select para KnockoutJS.

A tela:

dataannotations knockoutjs

Todos os campos são controlados pelo KnockoutJS.

Eu configurei alguns annotations para a model Person.

Models/Person.cs

public sealed class Person
    {
        [Display(Name = "Name")]
        [Required]
        [ValueDataBind("person.Name")]
        [CssClassTag("form-control")]
        public string Name { get; set; }

        [ValueDataBind("person.Id")]
        public string Id { get; set; }

        [Display(Name = "Email")]
        [Required]
        [EmailAddress]
        [EnableDataBind("isEnableToEdit")]
        [ValueDataBind("person.Email")]
        [CssClassTag("form-control")]
        public string Email { get; set; }

        [Display(Name = "Bith Date")]
        [DateDataBind("person.BithDate")]
        [CssClassTag("form-control")]
        public DateTime? BithDate { get; set; }

        [Display(Name = "Gender")]
        [EnableDataBind("isEnableToEdit")]
        [OptionsDataBind("genders", "person.Gender")]
        [CssClassTag("form-control")]
        public int? Gender { get; set; }
    }

No HTML o uso do HtmlHelper é mais ou menos assim:

Views/Person/Index.cshtml

@Html.InputFor(x => x.Person.Name)
@Html.InputFor(x => x.Person.BithDate)
@Html.SelectFor(x => x.Person.Gender)
@Html.InputFor(x => x.Person.Email)

Assim o código acima será renderizado como:

<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">

<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 }">

<select id="Person_Gender" name="Person.Gender" data-bind="enable: isEnableToEdit, options: genders, optionsText: 'Name', optionsValue:'Id', value: person.Gender" class="form-control"></select>

<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">

O código javascript abaixo é para configurar os dados que serão controlados pelo KnockoutJS na tela. A propriedade “isEnableToEdit” é uma função que é usado no data annotation EnableDataBind na model Person. Ela é uma regra que verificar se o nome da pessoa é maior que 2 e então retorna true/false.


 

Scripts/view-models/person.js

var personViewModel = function () {

    var _vm = null,

    createComputed = function () {
        _vm.isEnableToEdit = ko.computed(function () {
            return (_vm.person.Name() || '').length > 2;
        }, _vm);
    },

    init = function (model) {
        _vm = {
            person: ko.mapping.fromJS(model.Person),
            genders: [
                { Id: 0, Name: 'Select...' },
                { Id: 1, Name: 'Masc' },
                { Id: 2, Name: 'Fem' }
            ]
        };

        createComputed();

        var ctx = $('#person').get(0);
        ko.applyBindings(_vm, ctx);
    }

    return {
        init: init
    }

}();

Bom é isso. Esperto que tenha ajudado.

Abaixo encontrará alguns links úteis.

Data Annotations e HtmlHelpers de MVC para KnockoutJS

Annotations para KnockoutJS: Perguntas, sugestões ou críticas são bem vindas. Boa sorte!

Faça download completo do código fonte no github.

Veja um demo online dessa aplicação no codefinal.
Sobre o Autor:
Trabalha como arquiteto de soluções e desenvolvedor, tem mais de 16 anos de experiência em desenvolvimento de software em diversas plataformas sendo mais de 14 anos somente para o mercado de seguros.