How to apply the area correctly, so the order does not matter

I am trying to write unit test for a directive that matches the value for another input field. The problem is that if I define the element to be matched, before the element in which the directive is applied, it works fine, otherwise it fails.

It works great when the template

tpl = '<input name="verifyNewPassword" ng-model="verifyNewPassword" type="password"/>';
tpl += '<input name="newPassword" ng-model="newPassword" type="password" equals-to="userForm.verifyNewPassword"/>';

and it does not work when the template

tpl = '<input name="newPassword" ng-model="newPassword" type="password" equals-to="userForm.verifyNewPassword"/>';
tpl+='<input name="verifyNewPassword" ng-model="verifyNewPassword" type="password"/>';

here is my directive

.directive('equalsTo', function() {
    return {
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl) {
            var sc = scope;
            scope.$watch(attrs.ngModel, function() {
                var eqCtrl = scope.$eval(attrs.equalsTo);
                console.log('Value1: ' + ctrl.$viewValue + ', Value2: ' + eqCtrl.$viewValue);
                if (ctrl.$viewValue===eqCtrl.$viewValue || (!!!ctrl.$viewValue && !!!eqCtrl.$viewValue)) {
                    ctrl.$setValidity('equalsTo', true);
                    eqCtrl.$setValidity('equalsTo', true);
                } else {
                    ctrl.$setValidity('equalsTo', false);
                    eqCtrl.$setValidity('equalsTo', false);
                }
            });
        }
    };
})

here is my test code:

describe('Unit: Testing Directives', function() {
    var elm, scope;

    beforeEach(function() {
        module('mctApp');

        inject(function($rootScope, $compile) {
            scope = $rootScope.$new();
        });
    });

    function compileDirective(tpl) {
        if(!tpl) {
            tpl = '<input name="newPassword" ng-model="newPassword" type="password" equals-to="userForm.verifyNewPassword"/>';
            tpl += '<input name="verifyNewPassword" ng-model="verifyNewPassword" type="password"/>';            
        }
        tpl = '<form name="userForm">' + tpl + '</form>';

        inject(function($compile) {
            var form = $compile(tpl)(scope);
        });

        scope.$digest();

    }

    it('must be valid form as both values are equal', function() {
        scope.newPassword = 'abcdef';
        scope.verifyNewPassword = 'abcdef';
        compileDirective();                 
        expect(scope.userForm.$valid).toBeTruthy();
    });
});
+4
source share
3 answers

, , watch, $viewValue equals-to ngModelController - NaN, false .

http://plnkr.co/edit/OZVmogR6GT2pIKUrHpuX?p=preview

, ngModel, - "abcdef" - ​​ . ngModel.$viewValue , , , , DOM.

, , .

.directive('equalsTo', function() {
    return {
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl) {
            var sc = scope;
            scope.$watch(attrs.equalsTo + '.$viewValue', function() {
                var eqCtrl = scope.$eval(attrs.equalsTo);
                console.log('Value1: ' + ctrl.$viewValue + ', Value2: ' + eqCtrl.$viewValue);
                if (ctrl.$viewValue===eqCtrl.$viewValue || (!!!ctrl.$viewValue && !!!eqCtrl.$viewValue)) {
                    ctrl.$setValidity('equalsTo', true);
                    eqCtrl.$setValidity('equalsTo', true);
                } else {
                    ctrl.$setValidity('equalsTo', false);
                    eqCtrl.$setValidity('equalsTo', false);
                }
            });
        }
    };
})

http://plnkr.co/edit/OZVmogR6GT2pIKUrHpuX?p=preview

angular 1.3+, , .

+2

-, UX , , . () , ( ) . , . ( , . , , , .)

<input type="password" ng-model="password" required ng-pattern="/^(?=.*\w)(?=.*\W)/">
<input type="password" ng-model="passwordConfirmation" equal-to="password">

UX, ( AngularJS).


-, Angular. , . , , . , , .

.directive('equalTo', ['$parse', function ($parse) {
    return {
        require: 'ngModel',
        compile: function (element, attrs) {
            var getOtherValue = $parse(attrs.equalTo);

            return function link ($scope, $element, $attrs, ngModelCtrl) {
                ngModelCtrl.$validators.equalTo = function (value) {
                    return (value === getOtherValue($scope));
                };
            };
        }
    };
}])

( $parsers $setValidity $validators, AngularJS < 1.3)

, .


, , , ( equalTo ) .

+2

, $timeout . $timeout $digest, $digest.

.

$timeout(function(){
    $scope.$apply()
}

$timeout.flush() .

+2

Source: https://habr.com/ru/post/1568130/


All Articles