Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set validity of multiple inputs from a AngularJS Directive

I'm trying to create a directive which can be used to reset validation status of multiple input controls in a group, when one of the control's value is changed. Groups are identified by the attribute of the directive set in HTML. Ex: - Both of the From Date and To Date inputs resets the validity state when one of the controls input value is changed by the user

This is what I have so far

JS/Angular

angular.module('myModule').directive('groupedInputs', function () {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function (scope, element, attrs, ctrl) {
            element.on('change', function () {

                // Resetting own validity
                scope.$apply(ctrl.$setValidity('server', true));

                // Here I need to set the validity of the controls which
                // have the `GroupedInputs` directive with the 
                // same  attribute value
            });
        }
    };
});

HTML

<input name="FromDate" type="date" class="form-control" ng-model="model.FromDate" grouped-inputs="FromToDates">
<input name="ToDate" type="date" class="form-control" ng-model="model.ToDate" grouped-inputs="FromToDates">

It can reset the validity of the own input control, but can not access the other input controls with directive and same attribute value. What is the best possible angular way to access the other controls by querying the inputs with the same attribute?

like image 745
Nalaka526 Avatar asked May 23 '15 06:05

Nalaka526


People also ask

How are validations implemented in AngularJS?

AngularJS performs form validation on the client-side. AngularJS monitors the state of the form and input fields (input, text-area, select), and notify the user about the current state. AngularJS also holds information about whether the input fields have been touched, modified, or not.

What is restrict in Directive AngularJS?

Note: When you create a directive, it is restricted to attribute and elements only by default. In order to create directives that are triggered by class name, you need to use the restrict option. The restrict option is typically set to: 'A' - only matches attribute name.


2 Answers

I would try to approach this problem by implementing helper object to store group elements controllers with methods to add to the group and setValidity of all elements in the group.

Something like this:

angular.module('myModule').directive('groupedInputs', function() {

    var groupControls = {
        groups: {},
        add: function(name, ctrl) {
            this.groups[name] = this.groups[name] || [];
            this.groups[name].push(ctrl);
        },
        setValidity: function(name, key, value) {
            this.groups[name].forEach(function(ctrl) {
                ctrl.$setValidity(key, value);
            });
        }
    };

    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, element, attrs, ctrl) {

            // Add element controller to the group
            groupControls.add(attrs.groupedInputs, ctrl);

            element.on('change', function() {

                // When needed, set validity of elements in the group
                groupControls.setValidity(attrs.groupedInputs, 'server', false);
                scope.$apply();

            });
        }
    };
});

Demo: http://plnkr.co/edit/fusaaN6k9J5SZ7iQA97V?p=preview

like image 144
dfsq Avatar answered Oct 10 '22 12:10

dfsq


You could store all the controllers having the same group in an array:

angular.module('myModule').directive('groupedInputs', function () {
    var controllersPerGroup = {};

    return {
        restrict: 'A',
        require: '?ngModel',
        link: function (scope, element, attrs, ctrl) {
            var groupName = attrs.groupedInputs;
            var group = controllersPerGroup[groupName];
            if (!group) {
                group = [];
                controllersPerGroup[groupName] = group;
            }
            group.push(ctrl);

            element.on('change', function () {

                // Resetting own validity
                scope.$apply(ctrl.$setValidity('server', true));

                // all the other controllers of the same group are in the groups array.
            });
        }
    };
});

Don't forget to take care of removing the controllers once the element is destroyed, by listening to the $destroy event.

like image 31
JB Nizet Avatar answered Oct 10 '22 12:10

JB Nizet