Reputation: 8026
I need a directive which will parse user input to date and validate it. So I wrote the following:
myDirectives.directive('myDate', function($filter) {
'use strict';
return {
require:'ngModel',
restrict:'A',
link:function (scope, elem, attrs, ctrl) {
var dateFormat = attrs.myDate ? attrs.myDate : 'shortDate';
ctrl.$formatters.unshift(function(modelValue) {
return $filter('date')(modelValue, dateFormat);
});
ctrl.$parsers.unshift(function(viewValue) {
var date = new Date(viewValue);
if (isNaN(date)) {
ctrl.$setValidity('date', false);
return undefined;
} else {
var dateString = $filter('date')(date, dateFormat);
if (dateString !== viewValue) {
ctrl.$setViewValue(dateString);
}
ctrl.$setValidity('date', true);
return date;
}
});
}
};
});
Parsing need to occur only after when input loses focus, so I use another directive, which I found here. The problem is
ctrl.$setViewValue(dateString);
won't work, because as indicated in angularjs documentation, setViewValue() must be called from within a DOM event handler. What should I do to reflect back parsing result?
Upvotes: 4
Views: 9038
Reputation: 1
on html:
<input class="form-control""
type="date"
string-to-date
ng-model="val.VAL">
On Controller create a directive
.directive('stringToDate', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(value) {
return new Date(value);
});
ngModel.$formatters.push(function(value) {
var fechaactual = new Date(value);
return fechaactual;
});
}
};
})
note that the directive call stringToDate and you have to call it as string-to-date in the html. Dont not why :)
Upvotes: -1
Reputation: 2300
I've created a date parser that converts string to Date objects. You can also provide date formats you're using, as well as your date locale. It returns a Date object, valid or otherwise depending on the input.
There's also a directive that implements this parser so you can use it on an input field, for example.
https://github.com/dnasir/angular-dateParser
Upvotes: 2
Reputation: 25726
This should work:
var setter = $parse('ngModel').assign;
setter($scope,valueToSet);
$scope.$apply() // This may be needed depending on where its done.
Refenece: http://docs.angularjs.org/api/ng.$parse
Upvotes: 0
Reputation: 8026
Instead of
ctrl.$setViewValue(dateString);
I needed to write
elem.val(dateString);
and the problem was solved. So, my directive now looks like below:
myDirectives.directive('myDate', function ($filter) {
'use strict';
return {
require: 'ngModel',
restrict: 'A',
link: function (scope, elem, attrs, ctrl) {
var dateFormat = attrs.myDate ? attrs.myDate : 'shortDate';
ctrl.$formatters.unshift(function (modelValue) {
return (modelValue) ? $filter('date')(modelValue, dateFormat) : '';
});
ctrl.$parsers.unshift(function (viewValue) {
var date = new Date(viewValue);
if (isNaN(date)) {
ctrl.$setValidity('date', false);
return undefined;
} else {
var dateString = $filter('date')(date, dateFormat);
if (dateString !== viewValue) {
elem.val(dateString);
}
ctrl.$setValidity('date', true);
return date;
}
});
elem.unbind('input').unbind('keydown').unbind('change');
elem.bind('blur', function () {
scope.$apply(function () {
ctrl.$setViewValue(elem.val()); //this method name is misleading;
//it actually sets model value?!
});
});
}
};
});
Note, that I incorporated the code from another directive which was responsible for pushing view value to model, when focus is lost.
Upvotes: 2