There is no need for regex if you use type="email" . Angular will take care of validation for you.
angular.module('directives.emailUnique', []) .directive('emailUnique', ['$http', function ($http) { return { restrict: 'A', require: 'ngModel', link: function (scope, el, attrs, ctrl) { ctrl.$parsers.push(function (viewValue) { if (!viewValue) { ctrl.$setValidity('emailUnique', true); return undefined; } $http.get('/api/emailunique/' + viewValue).success(function (data) { if (data.data && data.data.unique) ctrl.$setValidity('emailUnique', true); else ctrl.$setValidity('emailUnique', false); }).error(function () { alert('Sorry, a technical issue prevents to validate your email.\n ' + 'Thanks to retry later.'); }); return viewValue; }); } }; }]);
Achieving a purely practical TDD to handle all cases, here is the specification:
describe('emailUnique directive', function () { var $scope, form, $httpBackend; beforeEach(function () { module('directives.emailUnique'); inject(function ($compile, $rootScope, _$httpBackend_) { $scope = $rootScope; $httpBackend = _$httpBackend_; var element = angular.element( '<form name="form" novalidate><input name="email" type="email" ng-model="model.email" required email-unique/></form>' ); $scope.model = { email: '' }; $compile(element)($scope); $scope.$digest(); form = $scope.form; }); }); afterEach(function () { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); }); describe('email uniqueness', function () { it('should return the current value if the email is a valid one', function () { $httpBackend.whenGET('/api/emailunique/ michael@gmail.com ').respond(200, {data: {unique: true}}); setViewValue(' michael@gmail.com '); $httpBackend.flush(); expect($scope.model.email).toBe(' michael@gmail.com '); $httpBackend.whenGET('/api/emailunique/ david@gmail.com ').respond(200, {data: {unique: true}}); setViewValue(' david@gmail.com '); $httpBackend.flush(); expect($scope.model.email).toBe(' david@gmail.com '); }); it('emailUnique validity should not be evaluated to true if email is invalid', function () { setViewValue('michael'); expect(form.email.$error.emailUnique).not.toBe(true); }); it('should set emailUnique validity to true if email is unique', function () { $httpBackend.whenGET('/api/emailunique/ michael@gmail.com ').respond(200, {data: {unique: true}}); setViewValue(' michael@gmail.com '); $httpBackend.flush(); expect(form.email.$error.emailUnique).toBe(false); }); it('should not set emailUnique validity to true if email is not unique', function(){ $httpBackend.whenGET('/api/emailunique/ david@gmail.com ').respond(200, {data: {unique: false}}); setViewValue(' david@gmail.com '); $httpBackend.flush(); expect(form.email.$error.emailUnique).toBe(true); }); it('should call emailUnique server api if email is valid, to check for uniqueness', function(){ $httpBackend.expectGET('/api/emailunique/ michael@gmail.com ').respond(200, {data: {unique: true}}); setViewValue(' michael@gmail.com '); $httpBackend.flush(); }); it('should set emailUnique to true if ' + 'it was first evaluated as not unique and then back to an invalid one', function(){ $httpBackend.whenGET('/api/emailunique/ david@gmail.com ').respond(200, {data: {unique: false}}); setViewValue(' david@gmail.com '); $httpBackend.flush(); setViewValue('michaelgmail.com'); expect(form.email.$error.emailUnique).toBe(false); }); }); function setViewValue(email) { form.email.$setViewValue(email); $scope.$digest(); } });
source share