Materialize data entry screens

Issue #590 wontfix
Brian Lewis repo owner created an issue

proposal on possible strategy….

Comments (4)

  1. Brian Lewis reporter

    Material Deisgn in data entry forms

    One characteristic of Mvc is the 'Html helpers' that are used to generate ui for a field in a table, based on the metadata in that fields definition. That is, the attributes of the field such as [Maxlength] , [Required] can generate the max-length and required attributes on the inut that is generated for the field.

    In Mvc, these helpers are written as extensions of the Html object exposed in the cshtml page - you use them like this:

    @Html.InputFor(m=> m.SchNo)
    

    Here m is the "model" in the page, the expressions returns a single property of that model.

    In Mvc usage, this model is an instance of a table value - so these helpers insert the value of the preropty into the generated control.

    To make helpers that work with angular we need:
    -- the model to represent a type, not an instance. No instance of the type is supplied when the page is requested - the instance data is inserted at the client.
    -- the markup generated by the helper is angularjs markup; that is, where an Mvc helper will write

    value= required max-length="50"

    a helper targeting angular js need to write

    ng-model="schNo" ng-maxlength="50" ng-required="true"

    Further, if targeting angularjs-material, the helper needs to respect the sophisticated css that governs the layout and animation in angularjs-material.

    Softwords.Web includes helpers in this design.

    To use these in a data entry cshtml page:

    1. Insert the references to the helpers at the top of the page:
    @using Softwords.Web.HtmlHelpers
    @using Softwords.Web.HtmlHelpers.Material
    @using System.Web.Mvc.Html
    
    1. Ensure that the model is fully marked up:
            [Display(Name = "Email 2", Description = "Alternative email address", Prompt = "Alternative email address", GroupName = "Contact Details")]
            [StringLength(100)]
            [EmailAddress]
            public string sEmail2 { get; set; }
    
    1. Referencce the model by pointing to the type; ie the Entity Framework entity definition class:
    @model Data.Models.Person
    
    1. Set up data entry using one of the available Html.ng..... helpers: e.g.
                  <div layout="row">
                    <md-input-container md-no-float flex>
                      @Html.ngInputFor(m => m.sEmail2)
                      @Html.ngErrorMessages(m => m.sEmail2)
                    </md-input-container>
                  </div>
    

    Expanding the ng helpers against sEmail as defined above, gives this:

                  <div layout="row">
                    <md-input-container md-no-float flex>
                      <md-icon class="material-icons">email</md-icon>
                      <input type="email"  title="Alternative email address" placeholder="Alternative email address" groupname="Contact Details" 
                      maxlength="100" ng-pattern="/^$|^([0-9a-zA-Z]([\+\-_\.][0-9a-zA-Z]+)*)+@(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]*\.)+[a-zA-Z0-9]{2,17})$/" 
                      ng-disabled="!vm.isEditing" ng-model="vm.model.sEmail2" 
                      name="sEmail2" id="sEmail2" 
                      aria-label="Alternative email address" aria-placeholder  />
                      <div ng-messages="vm.modelForm.sEmail2.$error" ng-if="vm.showErrors('sEmail2')" >
                        <p ng-message="maxlength">The field Email 2 must be a string with a maximum length of 100.</p>
                        <p ng-message="pattern">The Email 2 field is not a valid e-mail address.</p>
                        <p ng-message="required">Required</p>
                        </div>
                    </md-input-container>
                  </div>
    

    points to note:

    -- [EmailAddress] attribute creates email markup
    -- errors are handled
    -- aria markup for hearing impaired generated from Display attribute

    Example Helpers

    ngBindTo

    -- this is the simplest helper that is used inside an input on the page:

    <input @Html.ngBindTo(m=m>pxEmail) />

    ngInputFor

    -- this generates the appropriate input element:

    <md-container>
    @Html.InputFor(m=> m.pxEmail) 
    </md-container>
    

    ngInputFor can take an extra configuration object same as built in InputFor

     <md-input-container flex>
                      @Html.ngInputFor(m => m.studyHistLanguage1, new
                       {
                         aria_labelledby = "studyHistLanguage1_prompt",
                         aria_label = ""
                       })
                    </md-input-container>
    

    mdContainerFor

    -- This generates the input within a container, including the error messages - a simple default

                      <div layout-gt-sm="row">
                        @Html.mdContainerFor(m => m.sAddressState)
                        @Html.mdContainerFor(m => m.sAddressPostCode)
                      </div>
    

    expanded:

    <div layout-gt-sm="row">
        <md-input-container >
            <input type="text"  title="Address State" placeholder="Address State" groupname="Your address" maxlength="100" ng-disabled="!vm.isEditing" ng-model="vm.model.sAddressState" name="sAddressState" id="sAddressState" aria-label="Address State" aria-placeholder  />
        <div ng-messages="vm.modelForm.sAddressState.$error" ng-if="vm.showErrors('sAddressState')">
            <p ng-message="maxlength">The field State/Province must be a string with a maximum length of 100.</p>
            <p ng-message="required">Required</p>
        </div>
        </md-input-container>
        <md-input-container >
            <input type="text"  title="Address PostCode" placeholder="Address PostCode" groupname="Your address" maxlength="100" ng-disabled="!vm.isEditing" ng-model="vm.model.sAddressPostCode" name="sAddressPostCode" id="sAddressPostCode" aria-label="Address PostCode" aria-placeholder  />
            <div ng-messages="vm.modelForm.sAddressPostCode.$error" ng-if="vm.showErrors('sAddressPostCode')" >
                <p ng-message="maxlength">The field PostCode must be a string with a maximum length of 100.</p>
                <p ng-message="required">Required</p>
            </div>
        </md-input-container>
    </div>
    
  2. Brian Lewis reporter

    PROS and CONS

    PRO:

    declarative,

    reduces boilerplate coding

    full-featured ie includes err handling aria etc etc

    consistent

    CONS

    more to learn

    harder to customise by site

    less intuitive for those already familiar with angularjs / html

    @ghachey for your information really, if you are interested in pursuing I can work one small page on this technique.

    All the code is in Softwords.Web which is open source.

    [https://bitbucket.org/softwords/softwords.web/src/develop/HtmlHelpers/](https://bitbucket.org/softwords/softwords.web/src/develop/HtmlHelpers/)

  3. Log in to comment