I want to build a validation directive for credit card expiry dates. One model has the month, the other has the year. Both model need to know the value of the other model in order to computer if the date is expired.
I got it working that the directive (it's called validExpiryDate
) receives the models of the month and the year as parameters and then watches for changes in order to set the validity of the element.
However whenever I apply the valid-expiry-date
on an input field the content of ng-model is not shown. The input field just stays blank.
This is the directive:
app.directive('validExpiryDate', function(Stripe) {
return {
restrict: 'A',
require: 'ngModel',
scope: {
month: '=',
year: '='
},
link: function(scope, elem, attrs, controller) {
var state = function() { return {month: scope.month, year: scope.year};};
scope.$watch(state, function(v) {
var isValid = Stripe.card.validateExpiry(scope.month, scope.year);
controller.$setValidity('expiry-date', isValid);
}, true);
}
};
});
And this is my current template code:
<input id="e1" type="text" ng-model="a" month="a" year="b" />
<input id="e2" type="text" ng-model="b" month="a" year="b" />
<input id="e3" type="text" ng-model="c" valid-expiry-date month="a" year="b" />
<!-- works, but doesnt show the input of ng-model c in e3 -->
<br />
<input id="e4" type="text" ng-model="a" valid-expiry-date month="a" year="b" />
<input id="e5" type="text" ng-model="b" valid-expiry-date month="a" year="b" />
<!-- e4 and e5 show the correct valid class, but do not the model -->
Any idea why the content is not displayed?
Edit
As Ajay pointed out the problem is the scope. Read more here: Directive with scope breaking ngmodel of an input
On this new insight I adjusted my model to this:
app.directive('validExpiryDate', function(Stripe) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attrs, controller) {
var month = null;
var year = null;
var setValidity = function() {
var isValid = Stripe.card.validateExpiry(month, year);
controller.$setValidity('expiry-date', isValid);
};
scope.$watch(attrs.month, function(v) {
month = v;
setValidity()
});
scope.$watch(attrs.year, function(v) {
year = v;
setValidity()
});
}
};
});
not really pretty but it works.