AngularJs validation directive
I worked on a Stripe integration for OctoPerf, our load testing tool during the past weeks.
Validating a credit card number is really complex. Thankfully Stripe comes with a JavaScript API to validate the various fields of a credit card. But an AngularJs integration is not that straightforward.
Note:
The method explained here can be used to validate the other fields of the credit card.
The Custom Directive Solution¶
We are going to create a custom directive that uses the Stripe JS to do the validation. The error messages are displayed via ng-messages.
Injecting Stripe¶
The first step is to inject Stripe. To do so we need to create a service that provides it:
app.service('Stripe', ['$window',
function ($window) {
return $window.Stripe;
}
]);
Stripe is retrieved from the $window object. So we must include the Stripe Script in our HTML:
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
.
The Directive¶
Then we create a custom validation directive:
app.directive('stripeCardNumber', ['Stripe', function(Stripe) {
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, elm, attr, ctrl) {
if (!ctrl) return;
ctrl.$validators.cardNumber = function(modelValue, viewValue) {
return Stripe.card.validateCardNumber(viewValue);
};
}
};
}]);
Here we add our cardNumber validator to the enclosing controller and delegate the job to the function Stripe.card.validateCardNumber
.
The HTML code¶
Finally on the HTML view we can create the following form:
<form name="cardForm" class="form-validation">
<input type="text" class="form-control" name="number" ng-model="card.number"
placeholder="{{'Card number' | translate}}" stripe-card-number required>
<div ng-messages="cardForm.number.$error" class="text-danger" role="alert"
ng-show="cardForm.number.$touched">
<div ng-message="required">{{ 'You need to enter a card number.' | translate}}</div>
<div ng-message="cardNumber">{{ 'You need to enter a valid card number.' | translate}}</div>
</div>
</form>
Our stripe-card-number directive is added to the text input (we do not use a number input here).
Using ng-messages we can display an error message
when the validation fails. The ng-message="cardNumber"
value must match the name given in the stripeCardNumber directive ctrl.$validators.cardNumber
.
Ng-messages is a separate angular module. So we need to include the angular-messages script in our HTML and add ngMessages as one of our application dependencies.
Conclusion¶
We can easily do the same to validate the CVC:
ctrl.$validators.cvc = function(modelValue, viewValue) {
return Stripe.card.validateCVC(viewValue);
};
<div ng-messages="cardForm.cvc.$error" class="text-danger" role="alert"
ng-show="cardForm.cvc.$touched">
<div ng-message="required">{{ 'You need to enter a Card Verification Code.' | translate}}</div>
<div ng-message="cvc">{{ 'You need to enter a valid CVC.' | translate}}</div>
</div>
And a direct solution is to use existing AngularJs modules: