简体   繁体   中英

How to add/set validations (require, prestine etc) on custom angular directives

I have created an angular directive as follows:

angular.module('SharedModule')
    .directive('multiSelect', ['$ionicModal', multiSelect]);


function multiSelect($ionicModal) {
    return {
        restrict: 'E',
        template: [
            '<div ng-click="showItems($event)" class="item-icon-right item">',
            '{{text}}',
            '<i class="icon ion-ios-arrow-right"></i>',
            '</div>'
        ].join(""),
        scope: {
            'items': '=',
            'value': '=ngModel'
        },
        link: function (scope, element, attrs, $filter) {
            //validations
            //if (typeof attrs.required != "undefined"){
            //    // a value is required, hence invalidate this control.
            //
            //}

            //Some specific logic here. 

            scope.validate = function () {
                // validation that kicks in when user chooses to close the modal. 
            };

            scope.$on('$destroy', function () {
                scope.modal.remove();
            });
        }
    }
}

What this basically does is gives a user an option to select multiple contact types from a modal dialog used in an ionic app.

I use this directive in my html (inside a form) as follows:

<multi-select
    name="contactTypes"
    items="contact_types"
    text="Contact types"
    header-text="Choose contact types"
    allow-empty="false"
    ng-model="contact.contact_types"
    ></multi-select>

Question: I am not sure how to set ng-pristine,ng-required ng-untouched classes if the user has not selected anything. Where would the code to manage custom validation go? What do i need to do so that i could use this directive as any other input control with ng-model?

You will have to interact with ng-model , as described here (especially under "Custom Control Example"). To summarize:

  1. Start by requiring the ngModel :

     function multiSelect($ionicModal) { return { ... require: 'ngModel', ... }; } 
  2. In the link function get the ngModel and redefine $isEmpty . The default checks whether the value is undefined , '' , null or NaN . You probably want to add the empty array to this check, eg:

     link: function(scope, element, attrs, ngModel) { ... var originalIsEmpty = ngModel.$isEmpty; ngModel.$isEmpty = function(value) { return originalIsEmpty.call(ngModel, value) || value.length === 0; }; ... } 
  3. Having done this, you only need to add ng-required to your directive:

     <multi-select ... ng-required="true"></multi-select> 

    Angular will call your own implementation of $isEmpty and add the ng-invalid-required class to the <multi-select> element.

$pristine and $untouched may work out of the box. If not, you will have to add code that calls the appropriate methods of ngModel :

  1. Whenever the user opens the dialog - the control is touched, do ngModel.$setTouched() .
  2. Whenever the user presses "OK" in the dialog box AND actual changes are made - the control value has changed, it is no longer pristine, do ngModel.$setDirty() .

By the way, having access to ngModel in the link function makes the scope: { 'value': '=ngModel' } redundant.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM