【问题标题】:Angular : Adding Attribute directive on Element DirectiveAngular:在元素指令上添加属性指令
【发布时间】:2013-10-17 22:19:10
【问题描述】:

对于我的项目,我目前正在开发自定义表单/输入指令。

例如,我有以下指令:

angular.module('myApp').directive("textField", function() {
    return {
        restrict: 'E',
        replace: true,
        templateUrl : "/common/tpl/form/text-field.html",
        scope : {
            label   : "@",
            model   : "="
        }
    };
});

与相关的模板:

<div class="form-group">
    <label for="{{fieldId}}" class="col-lg-2 control-label">{{label |translate}}</label>
    <div class="col-lg-10">
        <input type="text" class="form-control" id="{{fieldId}}" ng-model="model" placeholder="{{label|translate}}">
    </div>
</div>

我有更多自定义字段(日期、选择、双选等...)

用法很简单:

<text-field label="app.myLabel" model="myObj.myAttribute"></text-field>

这个想法是通过避免在每个字段上冗长地添加标签来清理主模板。我相信非常普遍的需求。

现在的问题:

现在我需要为我的输入模型添加自定义验证。

我做了一个简单的方法是创建一个验证指令:

directive('myValidation', function (){
    return {
        require: 'ngModel',
        link: function(scope, elem, attr, ngModel) {
            ngModel.$parsers.unshift(function (value) {
                // do some validation
                return value;
            });
        }
    };
});

然后像这样使用它:

<text-field label="app.myLabel" model="myObj.myAttribute" myValidation="validationOptions"></text-field>

但这当然行不通,很简单,因为文本字段指令 replace=true “擦除”了它的元素上的验证指令。

有人能告诉一个人做“带有演示的自定义输入”指令的正确方法是什么,同时允许在指令上声明验证部分(这里是 text-field )并在指令的输入上使用?

例如,有没有办法说“我的元素指令上的属性将被'复制'到我的指令内部?”

又名:

<text-field label="app.myLabel" model="myObj.myAttribute" **myValidation="validationOptions"**></text-field>

会导致:

<div class="form-group">
        <label for="{{fieldId}}" class="col-lg-2 control-label">{{label |translate}}</label>
        <div class="col-lg-10">
            <input type="text" class="form-control" id="{{fieldId}}" ng-model="model" **myValidation="validationOptions"** placeholder="{{label|translate}}">
        </div>
    </div>

或者我只是错过了什么?

我想避免使用嵌入来解决这个问题,因为这会使表单模板看起来像这样:

<field label="myLabel">
     <input type="text" class="form-control" id="{{fieldId}}" ng-model="model" placeholder= {{label|translate}}">    
</field>

在我看来,这只是无用的冗长。但我开始问自己是否真的有另一种选择?

也许这个技巧可以在前(或后?)直接链接函数中完成,我会将属性/指令从文本字段标签复制到它的子(输入)标签?

有人可以为我照亮路吗?

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    你可以试试这个:

    • 写一个validate 指令。这将有一个控制器公开addValidationFunction(fn)getValidationFunction() 方法。

    • myValidation 指令需要validate 控制器并调用ctrl.addValidationFunction(myValidationImplementation),其中myValidationImplementation 是实现此特定指令验证逻辑的函数。

    • 编写另一个指令validateInner。这将需要来自其父级的可选validate 控制器。该指令还需要ngModel 控制器。如果找到validate 控制器,它会调用ctrl.getValidationFunction() 并使用ngModel 注册函数,即:

      require: ["^?validate", "ngModel"],
      link: function(scope,el,attrs,ctrls) {
          if( ctrls[0] != null ) {
              var validationFn = ctrls[0].getValidationFunction();
              // register validationFn with ngModel = ctrls[1]
          }
          ...
      }
      
    • 在你的textField的模板中:

      <input validate-inner type="text" class="form-control" id="{{fieldId}}" ng-model="model" placeholder="{{label|translate}}">
      

    用法:

    <text-field label="app.myLabel" model="myObj.myAttribute"
        validate my-validation="validationOptions"></text-field>
    

    注意 1:我不确定 replace:true 指令是否会擦除其他指令。如果是这样,这不是一致的行为。

    注意 2myValidation 指令被称为 &lt;xxx my-validation&gt;(注意 camelCase → dash-case)。如果您上面的代码不是错字,那么这就是为什么 &lt;text-field> 似乎会擦除 myValidation

    【讨论】:

    • 我产生了幻觉,replace: true 不会擦除其他指令,camelCase 问题就是这样。但你是对的,这是我最终不得不做的方法,谢谢
    猜你喜欢
    • 2023-03-24
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 2018-06-21
    • 2014-12-17
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多