As I mentioned in my comment, what is happening is that the datepicker directive is changing the model value from a String to a Date object. When ngPattern tried to validate the Date object it will fail because the string value of a Date is not going to match the pattern that you are using.
What you can do is create your own directive that hooks into the $parsers of the ngModelController to run your pattern check and then call $setValidity() based on what the value is. $parsers is actually built for this type of functionality where you want to run your own custom validation on a ngModel value.
Following these bullets is a directive that will accomplish the functionality that you want. I want to explain the logic in the directive before I show you the code:
- In order to add your own $parser you have to add a require for
ngModel in your directive definition so that you can access the ngModelController
- Because RegExp expects the pattern argument without the beginning and trailing slash, I removed them in the pattern directive argument
datepicker changes the model value from a String to a Date. Since datepicker uses unshift to add it's $parser function to the beginning of the $parsers array, we also need to use unshift to put our $parser before datepicker's $parser.
- As you mentioned, the
datepicker directive will take any value that it can parse into a date and use that for the model. In order to make sure that only dates which match the pattern are used, I'm returning undefined (as specified in the docs) for dates that don't match the pattern. I'm not doing this check for values that come in as a Date object since that means that it was chosen using the datepicker widget.
- As I just alluded to in the previous bullet, I'm not doing the validity check if the value is already a
Date object since that means that it was chosen using the datepicker widget and that means that it was a valid date.
directive code
app.directive('awDatepickerPattern',function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope,elem,attrs,ngModelCtrl) {
var dRegex = new RegExp(attrs.awDatepickerPattern);
ngModelCtrl.$parsers.unshift(function(value) {
if (typeof value === 'string') {
var isValid = dRegex.test(value);
ngModelCtrl.$setValidity('date',isValid);
if (!isValid) {
return undefined;
}
}
return value;
});
}
};
});
html - make sure that you don't forget to remove the beginning and trailing slash in the regex definition:
aw-datepicker-pattern="^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$"
And here is an updated plunker with my code.
So why again didn't ng-pattern work?
In case you didn't notice the root cause for why ng-pattern doesn't work when used with the datepicker directive is because the datepicker directive adds it's own ngModelController $parser to the beginning of the $parsers array by using unshift, which changes the model value from a String to a Date.
Dateobject, not as aString.datepickermakes sure the model value is aDateobject (as long as it can be parsed), but ng-pattern only works on strings. I was thinking of how to get your requirement to work but more importantly why do you need thatng-patternvalidation?datepickeris already forcing it to be a valid date