AngularJS directive to check that passwords match – Followup


This is a follow up on angularjs-directive-to-check-that-passwords-match by Bruno Scopelliti.

I found Bruno’s blog a while back when I started reading about AngularJS.
I started out by using the directive that is described in his blogpost but later dropped it in favor for a rewrite in “the Angular way”.

Bruno’s example relies on JQuery and DOM-event in order to do it’s magic, which does work fine, but for someone learning AngularJS it might not be the best example out there.
So here is my take on the very same directive:

app.directive('passwordMatch', [function () {
    return {
        restrict: 'A',
        scope:true,
        require: 'ngModel',
        link: function (scope, elem , attrs,control) {
            var checker = function () {

                //get the value of the first password
                var e1 = scope.$eval(attrs.ngModel); 

                //get the value of the other password  
                var e2 = scope.$eval(attrs.passwordMatch);
                return e1 == e2;
            };
            scope.$watch(checker, function (n) {

                //set the form control to valid if both 
                //passwords are the same, else invalid
                control.$setValidity("unique", n);
            });
        }
    };
}]);

This works by comparing variables on the current scope instead of reading values from Input elements using JQuery.

Usage:

<input type="password"  
     ng-model="password2" 
     password-match="password1" />

Important!:
This directive will only set the form control to valid or invalid when the passwords match or mismatch.
In order to show the errors in the form, do read up on form validation using AngularJS.
e.g. from Bruno’s blog here: http://blog.brunoscopelliti.com/form-validation-the-angularjs-way

11 thoughts on “AngularJS directive to check that passwords match – Followup”

  1. Since I just built a coffeescipt version, figured I’d share:

    directive = ->
      {
        restrict: 'A'
        scope: true
        require: 'ngModel'
        link: (scope, elem, attrs, control) ->
          checker = ->
            e1 = scope.$eval(attrs.ngModel)      
            e2 = scope.$eval(attrs.passwordMatch)
            e1 == e2
          scope.$watch checker, (n) ->
            control.$setValidity('unique', n)
      }
    
    app.directive 'passwordMatch', [ directive ]
    

  2. Hi,

    While using the directive, you are using like password-match=”password1″ ; But while defining the directive you are using app.directive(‘passwordMatch’ . How come password-match refers to passwordMatch?

  3. This is a feature of AngularJS, AngularJS tries to make JS idiomatic function names (camel case) to conform to HTML attributes when used in markup. so fooBar becomes foo-bar in markup.

  4. Directives are tricky to unit test. Here one way unit test this. I left the debug statements in to illustrate what the input tag looks like after the directive is applied.

    describe('passwordMatch Directive - ', function() {
        var scope, $compile, $window, element;
        beforeEach(module('BigModuleNameGoesHere'));
        beforeEach(inject(function(_$compile_, $rootScope, _$window_) {
            $compile = _$compile_;
            scope = $rootScope.$new();
            $window = _$window_;
        }));
    
        it('should indicate invalid when the passwords do not match.', function() {
            scope.password1 = '123';
            scope.password2 = '1234';
            element = $compile(angular.element(''))(scope);
            scope.$apply();
            console.debug('element html - ' + element.html());
            expect(element.html().indexOf('ng-invalid')).toBeGreaterThan(0);
        });
    
        it('should indicate valid when the passwords do not match.', function() {
            scope.password1 = '123';
            scope.password2 = '123';
            element = $compile(angular.element(''))(scope);
            scope.$apply();
            console.debug('element html - ' + element.html());
            expect(element.html().indexOf('ng-valid')).toBeGreaterThan(0);
        });
    });
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s