如何自动为输入字段添加标签?

时间:2013-06-14 09:47:42

标签: forms validation angularjs angularjs-directive

我正在与AngularJS合作开展更大的项目。因此,我希望尽可能简化单个表单的工作。由于我们还使用bootstrap,表单中单个输入字段的代码非常冗长,可能就像

<div class="control-group">
  <label class="control-label" for="inputEmail">Email</label>
  <div class="controls">
    <input type="text" id="inputEmail" placeholder="Email">
  </div>
</div>

如果我可以写一个像

这样的标签
<custom-input 
  label="Email" 
  name="inputEmail" 
  placeholder="Email" 
  type="text" 
  ... >
</custom-input>

相反,这将有助于保持代码清洁和工作简单。

为了实现这个目标,我正在开发一个自定义的AngularJS指令。我的指令当前使用类似于上面的bootstrap示例的模板,自动将标签分配给input-tag。此外,该指令的编译器功能将所有属性从自定义输入标记移动到实际输入标记,以便于自定义自定义输入标记。

app.directive('customInput', function() {
    return {
      require: 'ngModel',
      restrict: 'E',
      template: '<div>' + 
                    '<label for="{{ name }}">the label</label>' +
                    '<input id="{{ name }}" ng-model="ngModel" />' +
                '</div>',
      scope: {
              ngModel: '=',
              name: '@name',
          },
      replace: true,
      compile: function (tElement, tAttrs, transclude) {
            var tInput = tElement.find('input');

            // Move the attributed given to 'custom-input'
            // to the real input field
            angular.forEach(tAttrs, function(value, key) {
                if (key.charAt(0) == '$')
                    return;
                tInput.attr(key, value);
                tInput.parent().removeAttr(key);
            });

            return;
        },
    };
});

在Stack Overflow上,有很多关于自定义输入字段创建的问题,但它们与data bindingcustom formattingbinding to ng-repeat有关。

然而,我的方法有一个不同的问题:当数据绑定正常工作时,当输入字段需要时,Angular的集成表单验证模块会混淆。出于某种原因,验证不会识别新的输入字段,而是因为某些死引用而使表单无效,该引用具有空值。请参阅the minimal example

死亡参考来自哪里?如何更新验证模块的参考资料?有没有更好的方法来实现我的总体目标?

1 个答案:

答案 0 :(得分:4)

  1. 作为布尔属性,即使移动了属性,也会在div上保持相应的必需属性。
  2. 所需的属性未被移动,必须跳过它,因为没有值。我不知道如何使用没有值的javascript将其添加到元素中,但使用required="required"形式修复了
  3. 在移动属性时,使用transclude=true将在编译阶段后使用元素的副本,我认为这样可以保持设置所需的属性
  4. 由于某些原因,您必须分配更高的优先级,可能是因为ng-model,因为tattrs中的名称为ngModel而未从您的div中删除required="required" div不会消除优先权的需要)
  5. http://plnkr.co/edit/5bg8ewYSAr2ka9rH1pfE?p=preview

    我所做的只是将必需属性更改为 transclude: true, priority: 10, 并将这两行添加到指令声明中:

    ng-transclude

    我将{{1}}放在模板标签上,这样元素的内容就会出现在标签中,而你不必拥有该属性。