atwright147
atwright147

Reputation: 3811

AngularJS, Watch Multiple Fields in Directive

I am trying to watch and validate (together) two inputs in a form.

The problem I am having is that I can only seem to see the value of one of the fields at a time.

My HTML looks like this:

<form name="form">
    <label for="account-number">Account Number</label>
    <input type="text" name="account-number" id="account-number" ng-model="bank.accountNumber" modcheck><br>
    <label for="sort-code">Sort Code</label>
    <input type="text" name="sort-code" id="sort-code" ng-model="bank.sortCode" modcheck>
</form>

And the Directive looks like this:

angular.module('app', []).directive('myDirective', function() {
    'use strict';
    // Runs during compile
    return {
        // name: '',
        // priority: 1,
        // terminal: true,
        // scope: {}, // {} = isolate, true = child, false/undefined = no change
        // controller: function($scope, $element, $attrs, $transclude) {},
        require: 'ngModel', // Array = multiple requires, ? = optional, ^ = check parent elements
        restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment
        // template: '',
        // templateUrl: '',
        // replace: true,
        // transclude: true,
        // compile: function(tElement, tAttrs, function transclude(function(scope, cloneLinkingFn){ return function linking(scope, elm, attrs){}})),
        link: function($scope, elem, attrs, ngModel) {
            var _accountNumber, _sortCode;
            // from: http://stackoverflow.com/a/28332055/633056
            $scope.$watch(attrs.ngModel, function(val) {
                console.log(attrs.ngModel, attrs.name, val);
            });
            ngModel.$viewChangeListeners.push(function() {

                if (ngModel.$name == 'account-number') {
                    _accountNumber = ngModel.$viewValue;
                }
                if (ngModel.$name == 'sort-code') {
                    _sortCode = ngModel.$viewValue
                }
                console.log((_accountNumber && _accountNumber.length == 8), (_sortCode && (_sortCode.length >= 6 || _sortCode.length <= 8)));
            });
        }
    };
});

And I have prepared a CodePen here (you will need to open the dev tools console to see what's happening): https://codepen.io/atwright147/pen/LpgyWR/

How do you write a directive which can see the viewValue of multiple inputs at the same time?

Upvotes: 0

Views: 833

Answers (1)

Tristan
Tristan

Reputation: 3321

In a directive ngModel includes just that model value of the element that the directive is on. To get the value of the controller scope model you would need to include the scope in the directive using scope: { bank: '='} (the binding may be different depending on what you are wanting to do with the scope in the directive).

angular.module('app', []).directive('modcheck', function() {
    'use strict';
    // Runs during compile
    return {
        scope: { bank: '='}, // {} = isolate, true = child, false/undefined = no change
        // controller: function($scope, $element, $attrs, $transclude) {},
        require: 'ngModel', // Array = multiple requires, ? = optional, ^ = check parent elements
        restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment
        // compile: function(tElement, tAttrs, function transclude(function(scope, cloneLinkingFn){ return function linking(scope, elm, attrs){}})),
        link: function(scope, elem, attrs, ngModel) {
            var _accountNumber, _sortCode;
            // from: http://stackoverflow.com/a/28332055/633056
            scope.$watch('bank', function(val) {
                console.log('$watch:', scope.bank, attrs.name, val);
            },true);
            ngModel.$viewChangeListeners.push(function() {
                if (ngModel.$name == 'account-number') {
                    _accountNumber = ngModel.$viewValue;
                }
                if (ngModel.$name == 'sort-code') {
                    _sortCode = ngModel.$viewValue
                }

                console.log(('Overall:', _accountNumber && _accountNumber.length == 8), (_sortCode && (_sortCode.length >= 6 || _sortCode.length <= 8)));
            });
        }
    };
});

And the html

<form name="form">
    <label for="account-number">Account Number</label>
    <input type="text" name="account-number" id="account-number" ng-model="bank.accountNumber" modcheck bank="bank"><br>
    <label for="sort-code">Sort Code</label>
    <input type="text" name="sort-code" id="sort-code" ng-model="bank.sortCode" modcheck bank="bank">
</form>

Upvotes: 1

Related Questions