angualr custom instruction link function NgModelController Formatters and parsers

Keywords: angular AngularJS

Instructions are a powerful function provided by the angular framework, which is itself an MVVM framework.
In custom instructions, the interaction and changes between model and view are frequent. angular provides two pipeline arrays, $Formatters & $Parsers. Let's use custom instructions to control the changes between view and model.

Below is Official documents Definition:

$formatters:
Array of functions to execute, as a pipeline, whenever the bound ngModel expression changes programmatically. The $formatters are not called when the value of the control is changed by user interaction.Formatters are used to format / convert the $modelValue for display in the control.The functions are called in reverse array order, each passing the value through to the next. The last return value is used as the actual DOM value.

$parsers :
Array of functions to execute, as a pipeline, whenever the control updates the ngModelController with a new $viewValue from the DOM, usually via user input. See $setViewValue() for a detailed lifecycle explanation. Note that the $parsers are not called when the bound ngModel expression changes programmatically.The functions are called in array order, each passing its return value through to the next. The last return value is forwarded to the $validators collection.
Parsers are used to sanitize / convert the $viewValue.

First of all, there is always a connection between view and model. There will always be changes between them for some reasons. With input, keystrokes will lead to changes in view, business logic will lead to changes in model, etc.

Formters and parsers are attributes in ngModelController and are both an array of executable functions that can be used as a pipeline; all functions are executed as pipelines, what do you mean? That is to say, each function is connected, they are synchronous, non-asynchronous, and each function is executed sequentially, depending on the order in which the user adds executable functions to formatter and parsers, well that's it.

In addition, if parameters are needed for all added functions, then this parameter is the return value of $viewValue (the first function to execute) or the previous function, so if the next function needs parameters, the current function must return values.

function format(value) {
  if (value) {
    return value.toUpperCase();
  }
}
ngModel.$formatters.push(format);
\\**************************************
function parse(value) {
  if (value) {
    return value.toLowerCase();
  }
}
ngModelController.$parsers.push(parse);

These added executable functions are not executed manually, so when and how will they be executed?
For formatters attributes, there will be real-time monitoring events. When the data of ng-model changes programmatically, events will be triggered. At this time, all functions, including parameters and their return value operations, will be executed in the form of pipelines. For example, when we change the value through js, events will be triggered.

For parsers attributes, there are also event monitoring. When the ng-model data changes at the dom side, it triggers events and executes pipeline functions.

In practical application, the good application of these two attributes can reduce our own monitoring of data behavior.

In fact, careful will find that the two attributes involved in the scope of opposition, so, whether it is model or view changes, will be very helpful;

Parsers mainly focus on ngModelController.$viewValue, and its $setView value (); $viewValue is the actual value of the corresponding view when the instruction is used, $modelValue corresponds to the value bound by the instruction controller, $viewValue is associated with $modelValue through the $setViewValue method, $viewValue change does not necessarily cause the change of $view when the $view value changes. Start the function execution in parsers.

Here's an example.

//html
<div ng-app="myApp" ng-controller="myCtrl">
    <input ng-model="data" type="text" ng-click="ddd()" test />
    <span ng-click="changeModel()">{{data}}</span>
</div>

//js
angular.module('myApp', [])
.controller('myCtrl', function($scope){
   $scope.data = 'yellow'; 

   $scope.changeModel = function() {
           $scope.data = 'yellow'; 
    }
})
.directive('test', function(){
    return {
        require: 'ngModel',
        link: function(scope, elem, attrs, ngModel){
            ngModel.$formatters.push(function(value){
                //formats the value for display when ng-model is changed
                return 'brown'; 
            });
            ngModel.$parsers.push(function(value){
                //formats the value for ng-model when input value is changed
                return 'green'; 
            });

        },
        controller: function($scope,$transclude,$compile,$element) {

        }
    };
});

You can click on the link to run and observe the changes in real time.

More please Official documents

Posted by Hatdrawn on Sat, 05 Jan 2019 22:51:08 -0800