This chapter mainly talks about the interaction between directives and ngModel.
There is a built-in directive in angular called ngModel, which is the most important directive used by angular to process forms. In the source code, the formatting, parsing, and verification of the model value on the page are implemented by the controller ngModelController corresponding to the ngModel instruction. ngModelController provides many methods and properties. We can obtain the ngModelController of the built-in command ngModel through the require:'ngModel' of the custom command, and then operate the methods and properties of the ngModelController in the link function.
Next, let's talk about the methods and properties of ngModelController and their specific usage.
1. Two core properties $viewValue and $modelValue $viewValue is the value used by the directive to render the template, and $modelValue is the value circulated in the controller. Many times these two values are not the same. For example, when a date is displayed on the page, it may be "2018/04/23", but the corresponding value of this string in the controller may be an instance of a js Date object.
2. Three core pipelines $formatters $parses $validators and $asyncValidators
In addition to providing $viewValue and \modelValue, angular provides two methods for handling them, $parses and $formatters. $parsers: A converter from view value to model value. Changes in user input will trigger the pipeline function. The model value on the page is determined by the return value in the pipeline function. $formatters: Contrary to the role of $parsers, it is a converter from model value to view value, and its view value is determined by the return value in the corresponding pipeline function. $validators: is a json object
{ validateName: function(modelValue,viewValue){ return ... } }
When $setViewValue(value) is assigned to $modelValue, it will go through the $parsers pipeline, and when it goes through the $parsers pipeline, it will go through the $validators pipeline. Among them, validateName is the name of the validator, and the parameters modelValue and viewValue are and viewValue. If the return value is true, validateName is passed. Customize a validator:
< div class ="alert alert-danger" role ="alert" ng-show ="myForm.myWidget.$error.validCharacters" > < strong > Oh! </ strong > Does not meet custom validation rules! </ div >
ngModel.$validators.validCharacters = function(modelValue, viewValue) { var value = modelValue || viewValue; return /[0-9]+/.test(value); };
$asyncValidators: Also a json object, but can be used to handle asynchronous validation.
<input validate-name type="text" name="myWidget" ng-model="userContent" ng-model-options="{updateOn:'blur'}" class="form-control" required uniqueUsername> < div class ="alert alert-danger" role ="alert" ng-show ="myForm.myWidget.$error.uniqueUsername" > < strong > Oh! </ strong > Existing username! </ div >
app.directive('validateName',function($http,$q){ return { restrict:'A', require:'?^ngModel', link:function(scope,iele,iattr,ctrl){ ctrl.$asyncValidators.uniqueUsername = function (modelValue, viewValue) { var value = modelValue || viewValue; // Asynchronously verify if the username already exists return $http.get('/api/users/' + value). then( function resolved(res) { if (res.data){ // The username already exists, the verification fails, and the failure notification is delivered to the next promise. return $q.reject('res.data' ); } else { //The username does not exist, the verification is successful. return true } }, function rejected() { // Request failed }) }; } } });
3. Two core methods $setViewValue() and $render() $setViewValue(): update the view value. The reason is that this method is called on every input's input event. But if value is an object, not a string or numeric value, then we should make a copy before passing in the value in this method, because ngModel does not deeply detect changes to the object, it only looks at whether the reference to the object has changed. If you only change a property of the object, it will not go through the $parsers and $validators pipeline. Executing the $setViewValue() method will not trigger $digest. $render(): Called when the view needs to be updated. Due to the comparison mechanism of ngModel, $render() will only be called when both $modelValue and $viewValue have actually changed. That is, the $render function is responsible for synchronizing model values to the view.
Let's take a look at the instructions and controllers and their inner workings as shown in the figure:
There are also some common properties
Attributes | illustrate |
---|---|
$error | json object. It is a json object composed of all the verification names and failure information that failed to verify. |
$pending | json object. In-progress asynchronous validation will be placed in this object. |
$untouched | Boolean value. This value is true if the element has not lost focus. |
$touched | Boolean value. If the element has lost focus, this value is false. |
$pristine | Boolean value. This value is true if the element has not interacted with the user yet. |
$dirty | Boolean value. This value is true if the element has already interacted with the user. |
$valid | Boolean value. This is also very commonly used, that is, when all verifications (asynchronous and synchronous) are passed, it is true. |
$invalid | Boolean value. This is also very commonly used, that is, when all validations (async-sync), one or more of them fail, it is true. |
$name | string. Very simple, is to get the name attribute of the element. |
$isEmpty | When we need to determine whether the value of the input is empty, we can use this method. |