I am trying to understand the $formatters and $parsers of NgModelController and with this excellent example
I have created this demo. But having few questions which needs to clear
Below is my main code
<body ng-app="app">
<input type="text" ng-model="what" placeholder="directive Value" custom-formatter>
<input type="text" ng-model="what" placeholder="model value" >
change value {{ what }}
</body>
and
angular
.module('app')
.directive('customFormatter', ['$timeout',function($timeout){
return {
require: 'ngModel',
scope: {},
restrict: 'A',
link: function(scope, element, attrs, ngModelCtrl) {
// format text going to user ( on view )
ngModelCtrl.$formatters.push(function(modelValue){
console.log('MV:' + modelValue);
if (!modelValue) return;
else return modelValue.toUpperCase();
});
ngModelCtrl.$render = function () {
console.log('render called');
console.log(ngModelCtrl.$viewValue);
};
// scope.$watch('what', function() {
// console.log('watcher called');
// ngModelCtrl.$setViewValue({
// what: scope.what
// });
// });
ngModelCtrl.$parsers.push(function(viewValue){
console.log('VV:');
console.log(viewValue);
if(!viewValue) return;
else return viewValue.toLowerCase();
});
}
};
}]);
my few confusion are below also with my understanding , Please correct me if I am wrong
- in my understanding for current scenario
something changes in scope value ( i.e. in ng-model with custom directive input box ) than it means viewValue changed
and if something changed in input box without custom directive but same ng-model , than that means as modelValue changed
is that right?
When scope is set as isolated
{}
in custom directive then why changes reflects to other input box with sameng-model
valueBecause we have added
require:'ngModel'
in custom directive?
is this right?
- When do we need to call $render? according to $render document
It is called when the view needs to be updated.
So tried
ngModelCtrl.$render = function () {
console.log('render called');
console.log(ngModelCtrl.$viewValue;) // this gives UPPERCASE text
};
But output (the other text box and {{ expression }}) doesn't show uppercase value :(
Do it need to call $setViewValue
at it says
"Update the view value"
But how and where to call ? I tried
ngModelCtrl.$render = function () {
console.log('render called');
ngModelCtrl.$setViewValue({what : scope.what }) << doesn't work
console.log(ngModelCtrl.$viewValue;) // this gives UPPERCASE text
};
also see the note inside special notebox saying
if you are calling $setViewValue for an input element, you should pass the input DOM value. It's also important to note that $setViewValue does not call $render or change the control's DOM value in any way. If we want to change the control's DOM value programmatically, we should update the ngModel scope expression. Its new value will be picked up by the model controller, which will run it through the $formatters, $render it to update the DOM.
I do not understand this much? what means by control and control's DOM
also see a line
"When used with standard inputs, the view value will always be a string"
but when I look in console inside $parsers => it is Object {what: undefined}
is that the issue?
tries with
scope.$watch()
but no output as UPPERCASEscope.$watch('what', function() { console.log('watcher called'); ngModelCtrl.$setViewValue({ what : scope.what }); });
even this is never called , WHY so?
Please tell me when to use $watch and when to use $render with $viewValue and $setViewValue and how.