Reputation: 5485
I posted the same question in different form, but no one answered. I am not getting a clear picture of what the Formatters and Parsers do in angular js.
By the definition, both the Formatters and Parsers look similar to me. Maybe I am wrong, as I am new to this angularjs.
Array of functions to execute, as a pipeline, whenever the model value changes. Each function is called, in turn, passing the value through to the next. Used to format / convert values for display in the control and validation.
Array of functions to execute, as a pipeline, whenever the control reads value from the DOM. Each function is called, in turn, passing the value through to the next. Used to sanitize / convert the value as well as validation. For validation, the parsers should update the validity state using $setValidity(), and return undefined for invalid values.
Please help me to understand both features with a simple example. A simple illustration of both will be appreciated.
Upvotes: 107
Views: 102457
Reputation: 9497
This topic was covered really well in a related question: How to do two-way filtering in AngularJS?
To summarize:
Here is a simple example, building on an example in the [NgModelController api documentation][1]:
//format text going to user (model to view)
ngModel.$formatters.push(function(value) {
return value.toUpperCase();
});
//format text from the user (view to model)
ngModel.$parsers.push(function(value) {
return value.toLowerCase();
});
You can see it in action: https://plnkr.co/plunk/UQ5q5FxyBzIeEjRYYVGX
<input type="button" value="set to 'misko'" ng-click="data.name='misko'"/>
<input type="button" value="set to 'MISKO'" ng-click="data.name='MISKO'"/>
<input changecase ng-model="data.name" />
When you type a name in (view to model), you will see that the model is always lowercase. But, when you click a button and programatically change the name (model to view), the input field is always uppercase. [1]: http://docs.angularjs.org/api/ng/type/ngModel.NgModelController
Upvotes: 158
Reputation: 4701
Another usage for formatters and parsers is when you want to store dates in UTC time and display them in local time on inputs, I created the below datepicker directive and utcToLocal filter for this.
(function () {
'use strict';
angular
.module('app')
.directive('datepicker', Directive);
function Directive($filter) {
return {
require: 'ngModel',
link: function (scope, element, attr, ngModel) {
element.addClass('datepicker');
element.pickadate({ format: 'dd/mm/yyyy', editable: true });
// convert utc date to local for display
ngModel.$formatters.push(function (utcDate) {
if (!utcDate)
return;
return $filter('utcToLocal')(utcDate, 'dd/MM/yyyy');
});
// convert local date to utc for storage
ngModel.$parsers.push(function (localDate) {
if (!localDate)
return;
return moment(localDate, 'DD/MM/YYYY').utc().toISOString();
});
}
};
}
})();
It uses this utcToLocal filter that ensures the input date is in the correct format before converting to local time.
(function () {
'use strict';
angular
.module('app')
.filter('utcToLocal', Filter);
function Filter($filter) {
return function (utcDateString, format) {
if (!utcDateString) {
return;
}
// append 'Z' to the date string to indicate UTC time if the timezone isn't already specified
if (utcDateString.indexOf('Z') === -1 && utcDateString.indexOf('+') === -1) {
utcDateString += 'Z';
}
return $filter('date')(utcDateString, format);
};
}
})();
moment.js is used to convert local to utc dates.
pickadate.js is the datepicker plugin used
Upvotes: 7