从form.FormController直接访问表单元素?

时间:2014-07-04 14:12:54

标签: angularjs delegates angularjs-directive components decorator

我正在研究几个组件(指令)以帮助进行表单验证。我希望组件能够了解相关输入元素的状态(例如必需)。例如......

标记:

<form name="editUser">
    <control-label input="editUser.name">Name</control-label>
    <input type="text" name="name" ng-model="user.name" required/>
</form>

指令:

app.directive("controlLabel", function() {
  return {
    restrict: "E",
    replace: true,
    transclude: true,
    scope: {
      input: "=input"
    },
    template:
      '<label class="control-label">'+
        '<span ng-transclude>{{label}}</span>'+
        '<span ng-if="input.required"> (required!)</span>'+ // doesn't work?
      '</label>'
  };
});

输出:

<form name="editUser">
    <label>
        <span>Name</span>
        <span>(required!)</span>
    </label>
    <input type="text" name="name" ng-model="user.name" required/>
</form>

form.FormController的来源让我相信这是不可能的。有没有办法至少可以访问元素上的attrs?我想过使用装饰器,但到目前为止我还没弄清楚如何做到这一点。

2 个答案:

答案 0 :(得分:1)

首先,代码中存在错误。如果您使用transclude,则必须在指令中声明它,否则您将收到错误。

至于你的问题,在一个指令中,你可以访问DOM元素。对于这个特定的用例,您甚至可以在不创建隔离范围或额外属性的情况下完成:

app.directive("controlLabel", function() {
    return {
        restrict: "E",
        replace: true,
        scope: true,      // if needed, can also use empty isolated scope { }
        transclude: true, // must declare this
        template:
                '<label class="control-label">' +
                '<span ng-transclude>{{label}}</span>' +
                '<span ng-if="show"> (required!)</span>' +
                '</label>',
        link: function(scope, jqElem, attrs) {
            // check if next sibling of this directive is required
            scope.show = (jqElem.next().attr("required") === 'required');
        }
    };
});

现在你的控件标签真的很小而且DRY,并且逻辑很好地封装在一个指令中。唯一的要求是您的directive目标必须是标签的下一个兄弟:

<control-label>Name</control-label>
<input type="text" name="name" ng-model="user.name" required/>

当然,如果需要,您可以使用jquery - fu更改link功能以满足您的其他要求。

答案 1 :(得分:1)

您应该使用input.$validators.required代替input.required作为:

myApp.directive("controlLabel", function() {
  return {
    restrict: "E",
    replace: true,
    transclude: true,
    scope: {
      input: "=input"
    },
    template:
      '<label class="control-label">'+
        '<span ng-transclude>{{label}}</span>'+
        '<span ng-if="input.$validators.required"> (required!)</span>'+
      '</label>'
  };
});

Working Demo