ASP:NET Core Mvc Controls Toolkit automatically processes input fields both to parse validation Html5 data- attributes for creating client validation rules, and to apply fallbacks to Html5 inputs that are not supported by the browser (actually one may force the fallback also when the input type is supported by the browser).

mvcct-enhancer takes care of orchestarting and applying the above transformations both to the initial page, and to any dynamically created Html content. It was conceived to mitigate the typical problems faced when developers enrich Html with widgets and plugins written by various authors and based on different technologies. Namely:

  • problems caused by the wrong order plugins are applied to their target Html
  • panic when the same plugins must be applied also to the Html created dynamically or received by ajax calls. In fact, putting everything in the jQuery.ready(...) is easy...but then we have to re-implement a similar code each time we create dynamic content! Several jQuery widgets automatically enhance our Html at the price of almost no programming effort, thanks to data- attributes and to a document parsing performed on the document ready event, but then all these tranformations are not automatically applied also to dynamic content!

With mvcct-enhancer developers may decide once and for all the kind of transformations to apply to our html, and their order, and then having them applied automatically to all our pages, and dynamic content.

With mvcct-enhancer developers may coordinate easily modules loaded asynchronously and modules loaded sinchronously, so that they apply in the right order!

mvcct-enhancer creates an unique centralized registry of all Html transformations/widgets and uses an unique options object to pass options to all registred modules.

mvcct-enhancer has no dependency on other js libraries and comes with just a single transformation module that applies a minimal fallback for Html5 inputs that either are not supported by the browser or that the developer would like to substitute with widgets. Adding other transformations is as easy as:

  1. writing simple wrappers around already existing modules
  2. registering the wrapped module by calling the .register(...) method.

Here, you will find just documentation for the "common usage" of mvcct-enhancer with the standard Mvc Controls Toolkit project configuration. Click here for advanced topics.

For a comprehensive discussion about the motivations and the foundational priciples behind mvcct-enhancer please refer to this blog post.

Important: all mvcct-enhancer distributions contain TypeScript declaration files in case the module is referenced from TypeScript.

When mvcct-enhancer is loaded synchronously an enhancer object is contained in the mvcct.enhancer javascript variable. In case of AMD, or Node.js type loading the same object is obtained as valued of the mvcct-enhancer module (see here for more infos about asynchronous loading).

In order to have all modules registred with mvcct-enhancer apply all transformations/processing on dynamically created nodes just call mvcct.enhancer.transform(node) on the root of the newly created node(s).

The mvcct-templates npm module loaded during installation automatically configure mvcct-enhancer to furnish both validation and html5 fallback with bootstrap widgets. So if you don't change the project configuration, you should just modify the options object passed to it, that, as detailed in the installation procedure, is contained in wwwroot/startupjs/startup.js. Below, the mvcct-enhancer basic options. Other options are added by all other JavaScript modules and are documented with those files.

The browserSupport.fallbacks option property declares the type of fallback provided, and if for a specific input the fallback must be forced also in case of browser support:

                    force: true/false,
                    type: 1..3
            range?: ...,
            date?: ...,
            month?: ...,
            week?: ...,
            time?: ...,
            datetime?: ...,
            email?: ...,
            search?: ...,
            tel?: ...,
            url?: ...,
            color?: ...,

The browserSupport.cookie and >browserSupport.forms string properties when set to a not null value cause information on the Html5 support be sent to the server, in a cookie/hidden field with the name specified in the string. When using mvcct-enhancer with the Mvc Controls Toolkit it is obligatory to set at least one of them to "_browser_basic_capabilities", to inform the model binder on the format being used for numbers and dates/times. The default wwwroot/startupjs/startup.js file selects the cookie.

type is automatically set by the JavaScript file that provides the fallback (in the default project setting bootstrap-html5-fallback), so the only parameter that usually must be configured is force. When set to true fallback is forced otherwise Html5 input is used when supported.

The mvcct.enhancer object offers also usefull methods for parsing and formatting strings according the the currently set client culture:

.format(type, value, [invariant]) 
.parse(type, stringValue, [invariant])

Here type is not a JavaScript type but the name of the input type that is supposed to handle that type of value('date', 'datetime', 'range', etc.).

format takes a javascript object (date or number depending on the input tipe) and transforms it in a properly formatted string, while parse performs the inverse transformation. In case of fallback the formats specified in the editFormats(or their defaults) are used. If the third optional argument is true parsing/formatting are done using the invariant culture (the one used by native Html5 inputs), otherwise the right culture is auto-detected as the culture being used by the widget passed as type: ie invariant culture for Html5 inputs or for fallbacks that handle the same format, and the current client culture for not-invariant widgets. Forcing the invariant culture may be useful for some custom processing of the original input field (for instance processing min/max or step attributes to set some fallback widget options).

The default editFormats are:

     dateFormat: { "date": "short" },
     timeFormat: { "skeleton": "Hms" },
     timeFormat1: { "skeleton": "Hms" },
     datetimeFormat: { "datetime": "short" },
     datetimeFormat1": { "datetime": "short" },
     monthFormat: { "date": "short" },
     weekFormat: { "date": "short" }

For information on the formats syntax, please refer to the Globalize library documentation. You may supply different values, but, pay attentions, that fallback widgets do not support all formats.

The .getSupport() method returns an object containing information about the browser Html5 input support. More specifically:

  • The Html5InputOriginalSupport property contains the following support object:

                number: true/false,
                range: true/false,
                date: true/false,
                month: true/false,
                week: true/false,
                time: true/false,
                datetime: true/false,
                email: true/false,
                search: true/false,
                tel: true/false,
                url: true/false,
                color: true/false,

    Where true means the input type is supported. If the mvcct.enhancer.input.basic.js basic fallback module is loaded and registered by calling the mvcct.enhancer method addBasicInput(Globalize), then Html5 fallback is turned on. and all Html5 inputs that are not supported are transformed into text inputs and their content is converted into the current "locale" (this means, for instance, that dates are transformed from the date input ISO format into a format like mm/dd/yy). Available, also a more complete fallback based on bootstrap widgets: bootstrap-html5-fallback When bootstrap.html5.fallback.js is loaded after mvcct.enhancer.input.basic.js the addBasicInput(Globalize) is updated to load also all bootstrap widgets.

    Please notice that the addBasicInput must be passed a Globalize object, that is needed for the above transformations.

    Important: all input fallback features and all Globalization library stuffs are loaded automatically in the default Mvc Controls Toolkit template scaffolded during installation.

  • The Html5InputSupport property, instead, contains information on the fallback provided:

                number: number;
                range: number;
                date: number;
                month: number;
                week: number;
                time: number;
                datetime: number;
                email: number;
                search: number;
                tel: number;
                url: number;
                color: number;

    Four integer values are used: 1 no support, 2 not ISO fallback, 3 ISO fallback, 4 native support.

    Iso fallback means that numbers and dates/time are stored in the input field in exactly the same format of native input type (international ISO format). not ISO fallback is the most common, since most of available widgets use current "locale" formats(ie mm/dd/yy like dates).

    A value of, say 3 doesn't mean necessarely that the browser has no native support since, as discussed previously, the developer may force the usage of the available fallback.

Both Html5InputOriginalSupport and Html5InputSupport objects are serialized and inserted in the cookie/hidden field sent to the server into an unique array of name/value pairs:

    {Key: 'Html5InputSupport.number', Value: 2},
    {Key: 'Html5InputOriginalSupport.number', Value: false}

The Html5InputSupport is needed by the Mvc Controls Toolkit model binder, but is also publically available via Dependency Injection, by requiring the class MvcControlsToolkit.Core.Options.Html5InputSupport. The Html5InputOriginalSupport is less usefull, and is not immediately available, but its data are stored in the global options dictionary under the "Browser" key, so you may define a similar option object also for it.

Dependencies propagation module

In order to help modules registred with mvcct-enhancer to enhance Html, it provides a simple dependency propagation engine. We may declare that an input node input1 depends on input2, according to a function f(). After that, each time input 2 changes (becuase of an user action) f() will be invoked on input1, and recursively all inputs depending on input1 will have their f() invoked, and so on. Infinite loops are prevented by stopping the propagation when it returns on an already visited node.

A dependency is declared with the following mvcct.enhancer method:

           sourceNode, //tracked node
           targetNode, //dependent node
           eventNames: //array containing the names of all 
                       //events that will trigger the propagation(ie ['blur', 'keypress'...], etc
           action: // invoked function function(targetNode, sourceNode) => void); 

name identifies the type of dependency. If you want your dependencies interact globally with all others, please set name="main". When the value of an input is changed programmatically, dependency propagation may be started by triggering the "_enhancer.dependency."+name event.

Important!, since mvcct.enhancer doesn't depend on jQuery all above events are not defined with jQuery.

Fork me on GitHub