Angular:在Element Directive上添加Attribute指令

时间:2013-10-10 08:39:28

标签: javascript angularjs

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

例如,我有以下指令:

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>

但是当然这不起作用,很简单,因为text = field指令是replace = true“擦除”它的元素上的验证指令。

有人可以告诉一个用“自定义输入和演示”指令的正确方法是什么,同时允许在指令(这里是文本字段)上声明验证部分并在指令的输入上使用?

每个例子,有没有办法说“我的元素指令上的属性将'复制'到我的指令中?”

又名:

<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>

在我看来这是无用的冗长。但我开始问自己是否还有其他选择?

也许这个技巧可以在pre(或post?)directve链接函数中完成,在那里我将属性/指令从text-field标签复制到它的child(input)标签?

有人可以为我点亮路吗?

1 个答案:

答案 0 :(得分:3)

你可以试试这个:

  • 编写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指令是否会擦除其他指令。如果是这样,那就不一致了。

注意2 myValidation指令被称为<xxx my-validation>(注意camelCase→dash-case)。如果您的上述代码不是拼写错误,那么这就是<text-field&gt;好像擦了myValidation