简体   繁体   中英

Angular 1.5 custom validation directive for ng-messages

I'm working on custom directive for ng-messages where with adding one directive "custom-validation" to input field:

 <input name="inputName" ng-model="vm.inputName" custom-validation="vm.validationConfig" class="form-control" />

and defining object with configuration:

    vm.validationConfig = {
        "rules": [
            { "ng-minlength": 2 },
            { "ng-maxlength": 20 },
            { "ng-pattern": "/^[a-zA-Z0-9]$/" },
            "required"
        ],
        "messages": [
            { "required": "This field is required" },
            { "minlength": "Message must be over 2 characters" },
            { "maxlength": "Message must not exceed 20 characters" },
            { "pattern": "Message must contain letters or numbers only" }
        ]
    };

After adding directive input should be simply wrapped like this:

   <form name="inputName-form" ng-class="{ 'has-error':  inputName-form.inputName.$invalid }" novalidate>
        <input name="inputName" type="number" ng-model="inputName" max="100" class="form-control" required>
        <div ng-messages="inputName-form.inputName.$error" class="error-messages" role="alert"  ng-if="inputName-form.inputName.$invalid ">
            <div ng-message="number" class="message">Should be a number</div>
            <div ng-message="max" class="message">The number is too large.</div>
            <div ng-message="required" class="message">The field is required.</div>
        </div>
    </form>

So far my directive looks like this:

(function () {
    "use strict";
    var module = angular.module('app');

    function isObject(obj) {
        return obj === Object(obj);
    }
    var validate = function () {
        return {
            restrict: 'A',
            replace: true,
            transclude: "element",
            scope: {
            },
            link: function (scope, element, attrs) {
                var input = attrs.name;
                //for some reason there was a space with the name
                input = input.split(' ').join('');
                scope.inputName = input;
                //create a unique form name
                scope.formName = input + "-form";
                //remove doubled form control
                element.removeClass('form-control');
                //get configuration
                scope.config = scope.$parent.vm.validationConfig;
                //object to set if form is valid or not
                scope.isValid = scope.$parent.vm.formValid;
                var formInputId = scope.formName + "." + scope.inputName;
                scope.$watch('scope.formName.$valid', function (newVal) {
                    scope.isValid[formInputId] = newVal;
                });
                var i, obj, key, val;
                scope.input = scope[attrs.name];
                //parse configuration object
                if (scope.config !== undefined) {
                    for (i = 0; i < scope.config.rules.length; i++) {
                        if (isObject(scope.config.rules[i])) {
                            obj = scope.config.rules[i];
                            key = Object.keys(obj)[0];
                            val = obj[key];
                            attrs.$set(key, val);
                        } else {
                            attrs.$set(scope.config.rules[i], true);
                        }
                    }
                    //parse messages
                    scope.msg = '';
                    for (i = 0; i < scope.config.messages.length; i++) {
                        obj = scope.config.messages[i];
                        key = Object.keys(obj)[0];
                        val = obj[key];
                        var newMessage = '<div ng-message=' + key + '>' + val + '</div>';
                        scope.msg = scope.msg.concat(newMessage);
                    }
                }
            },
            template: '<form name="{{formName}}"><div ng-transclude></div><div ng-messages="formName[inputName].$error">{{msg}}</div></form>'
        };
    };
    module.directive('customValidation', validate);
}());

There are at least two problems with this directive realated to template

<div ng-messages="formName[inputName].$error">{{msg}}</div>
  1. I don't know how to properly access formName.inputName.$error ?
  2. {{msg}} is dispalying all the ng-messages as a string, I was trying to compile it before but it didn't work ...

Thanks

Finally I have solved the problem with the below code.

(function () {
    "use strict";
    var module = angular.module('app');
    function isObject(obj) {
        return obj === Object(obj);
    }
    var validate = function ($compile) {
        return {
            restrict: 'A',
            scope: {},
            link: function (scope, element, attrs) {
                scope.formName = attrs.name + "Form";
                scope.ngMsgs = scope.formName + "." + attrs.name + ".$error";
                scope.config = scope.$parent.vm.validationConfig;
                var i, obj, key, val;
                if (scope.config !== undefined) {
                    for (i = 0; i < scope.config.rules.length; i++) {
                        if (isObject(scope.config.rules[i])) {
                            obj = scope.config.rules[i];
                            key = Object.keys(obj)[0];
                            val = obj[key];
                            attrs.$set(key, val);
                        } else {
                            attrs.$set(scope.config.rules[i], true);
                        }
                    }
                    scope.msg = '';
                    for (i = 0; i < scope.config.messages.length; i++) {
                        obj = scope.config.messages[i];
                        key = Object.keys(obj)[0];
                        val = obj[key];
                        var newMessage = '<div ng-message=' + key + '>' + val + '</div>';
                        scope.msg = scope.msg.concat(newMessage);
                    }
                }
                var wrapper = angular.element
                    (
                    '<form name=' + scope.formName + ' ng-class="{ ' + "'has-error'" + ':  ' + scope.formName + '.' + attrs.name + '.$invalid }" novalidate>'
                    );
                element.after(wrapper);
                element.removeAttr("custom-validation");
                wrapper.append(element);
                wrapper.append("<div ng-messages=" + scope.ngMsgs + " class='error-messages' role='alert' ng-if='" + scope.formName + '.' + attrs.name + ".$invalid'>" + scope.msg + "</div>");
                $compile(wrapper)(scope);
            }
        };
    };
    module.directive('customValidation', validate);
}());

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