ngModel.$ parsers无法在指令中使用 [英] ngModel.$parsers not working in directive

查看:80
本文介绍了ngModel.$ parsers无法在指令中使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想动态地将指令添加到表单元素(输入,选择,文本区域...)

I want to dynamically add directives to form elements (input,select,textarea...)

<div ng-app="app" ng-controller="ctrl">
    <form form-validator>
    <input type="text" ng-model="model1">
    <input type="text" ng-model="model2">
    <input type="text" ng-model="model3">
    <textarea ng-model="model4"></textarea>
    <select>
       <option ng-model="model5" value="1">Name</option>
    </select>
    </form>
</div>

指令

var app=angular.module('app',[])
.controller('ctrl',function($scope){

})
.directive('formValidator',function($compile){
    return{
        restrict: 'A',
        link: function(scope, elem, attrs){
            //is it possible to do this with one line of code?
            elem.find('input').attr('validate-field','');
            elem.find('select').attr('validate-field','');
            elem.find('textarea').attr('validate-field','');
            $compile(elem.contents())(scope);
        }
    }
})
.directive('validateField',function(){
    return{
        restrict: 'A',
        require:['^ngModel'],
        link: function(scope, element, attr, ctrls){
            var valid = false;
            var ngModel = ctrls[0];
            alert('before validation');
            ngModel.$parsers.unshift(function (value){ 
               alert('validating');
               valid = validator(value);
               ngModel.$setValidity('required', valid, ctrls);
               return valid ? value : undefined;
            });
        }
    }
});

上面的代码能够将validate-field属性添加到表单元素:

The code above was able to add validate-field attribute to form elements:

<input type="text" ng-model="model1" validate-field>

问题是未调用ngModel.$parsers.unshift,已调用alert('before validation');,但未调用alert('validating');.

The problem is ngModel.$parsers.unshift is not being called, alert('before validation'); is called but alert('validating'); is not being called.

我想念什么?

推荐答案

当前,正在编译所有子validateField指令后,您正在formValidator指令链接函数进行评估.因为link: function(){ .. }函数被认为与postLink函数相同,所以在所有子scope链接准备就绪后才调用该函数.您的情况也是如此.

Currently what happening is you formValidator directive link function is evaluating after all child validateField directive gets compiled. Because link: function(){ .. } function is considered as same as postLink function, which gets called after all children scope linking ready. Same thing is happening in your case.

因此,我想说的是确实要调用您的链接函数,以确保在指令被编译之前它将添加validate-fields.为此,您需要使用preLink函数.

So I'd say say that do call your link function to ensure that it will add validate-fields before directive gets compile. For that you need to use preLink function.

.directive('formValidator', function($compile) {
    return {
      restrict: 'A',
      link: {
        pre: function(scope, elem, attrs) {
          elem.find('input').attr('validate-field', '');
          elem.find('select').attr('validate-field', '');
          elem.find('textarea').attr('validate-field', '');
          $compile(elem.contents())(scope);
        }
      }
    }
})

在此处插入代码

更好的版本是只编译一次父指令

More better version would be compile parent directive only once

  .directive('formValidator', function($compile) {
    return {
      restrict: 'A',
      compile: function(elem, attrs) {
        elem.find('input').attr('validate-field', '');
        elem.find('select').attr('validate-field', '');
        elem.find('textarea').attr('validate-field', '');
        //removed to avoid infinite directive compile
        elem.removeAttr('form-validator');
        var linkFn = $compile(elem);
        return function(scope, element, attr) {
          linkFn(scope);
        }
      }
    }
  })

在此处检查

这篇关于ngModel.$ parsers无法在指令中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆