防止指令属性重复?

时间:2014-11-10 07:50:28

标签: angularjs

我有一个指令,它在引导程序form-group / form-control

中添加一个输入

它监视字段的$valid$invalid值,并设置适当的引导错误/有效的css类。

这是标记:

<fe-input ng-model='user.first_name' field='first_name' submitted='submitted' label='First Name'></fe-input>
<fe-input ng-model='user.last_name'  field='last_name'  submitted='submitted' label='Last Name'></fe-input>
<fe-input ng-model='user.phone'      field='phone'      submitted='submitted' label='Phone'></fe-input>

它依赖于在用户尝试提交表单时设置的范围变量submitted(因此我们在用户执行任何操作之前不显示无效字段)

您可以看到重复次数

  • field = model.field:字段名称始终与模型字段名称相同
  • submitted='submitted':每次都重复

理想情况下,我想将其简化为:

<fe-input ng-model='user.first_name' label='First Name'></fe-input>
<fe-input ng-model='user.last_name'  label='Last Name'></fe-input>
<fe-input ng-model='user.phone'      label='Phone'></fe-input>

它会强制执行:

  • 表单字段的名称始终与模型的字段名称相同
  • submitted在父作用域上是隐式必需的

问题:

  • 这可能吗?
  • 如果是的话,有关如何实现这一目标的任何建议吗?

Plunker:

Here is a plunker显示我目前所拥有的内容。

指令源代码:

这是我的指令的html模板:

<div class="form-group" ng-class="{ 'has-success': submitted && isValid,
                                    'has-error'  : submitted && isInvalid }">
    <label class="control-label" for="{{ field }}">
        {{ label }}
    </label>
    <input type="text"
           class="form-control"
           ng-model="model"
           name="{{ field }}"
           id="{{ field }}"
           required>
</div>

和指令来源:

angular.module('directive.form-elements', []).directive('feInput', function() {
    return {
        restrict: 'E',
        require: ['^form'],
        scope: {
            model: '=ngModel',
            label: '@',
            field: '@',
            submitted: '='  // feedback only when the form has been submitted
        },
        templateUrl: 'components/form-elements/input.html',
        replace: true,
        link: function (scope, element, attrs) {
            scope.$parent.$watch('form.'+scope.field+'.$valid', function(isValid) {
                scope.isValid = isValid;
            });
            scope.$parent.$watch('form.'+scope.field+'.$invalid', function(isInvalid) {
                scope.isInvalid = isInvalid;
            });
        }
    };
});

提交:

submitted是表单控制器范围内的变量,由表单中的所有输入元素共享。它仅用于在用户实际尝试提交表单时启用有效/无效样式

angular.module('myApp').controller('UserCtrl', function($scope) {

    $scope.submitted = false;

    $scope.submit = function(form) {
        $scope.submitted = true;
        if (!form.$valid)
            return;
        // do submit
    });

1 个答案:

答案 0 :(得分:1)

一种解决方案是创建一个处理重复内容的父指令。 HTML看起来像这样:

<form name="userForm" fe-form="user">
  <fe-input field='first_name' label='First Name'></fe-input>
  <fe-input field='last_name'  label='Last Name'></fe-input>
  <fe-input field='phone'      label='Phone'></fe-input>
  <button type="submit">Save</button>
<form>

父指令:

angular.module('directive.form-elements', []).directive('feForm', function() {
return {
    controller: function($scope, attrs) {
      var formName = $attrs.name;
      var submitted = false;

      this.hasSuccess = function(field) {
        return submitted && $scope[formName][field].$valid;
      };

      this.hasError = function(field) {
        return submitted && $scope[formName][field].$invalid;
      };

      this.setSubmitted = function(value) {
        submitted = value;
      }
    },
    link: function (scope, element, attrs, controller) {
      controller.model = $scope[$attrs.feForm];
      element.on('submit', function(event) {
          controller.setSubmitted(true);

重要的是它有一个可以被你的其他指令使用的控制器。我们还封装了错误和成功状态。

您的原始指令:

angular.module('directive.form-elements', []).directive('feInput', function() {
return {
    restrict: 'E',
    require: ['^form', '^feForm'],
    scope: {
        field: '@',
        label: '@'
    },
    templateUrl: 'components/form-elements/input.html',
    replace: true,
    link: function (scope, element, attrs, controllers) {
        var feFormController = controllers[1];

        scope.model = feFormController.model;
        scope.hasSuccess = feFormController.hasSuccess;
        scope.hasError = feFormController.hasError;
    }
};
});

这里我们可以使用父指令的控制器。

模板的小修改:

<div class="form-group" ng-class="{ 'has-success':  hasSuccess(field),
                                'has-error'  : hasError(field) }">
<label class="control-label" for="{{ field }}">
    {{ label }}
</label>
<input type="text"
       class="form-control"
       ng-model="model[field]"
       name="{{ field }}"
       id="{{ field }}"
       required>
</div>

请理解,虽然此代码可能适合您,但它可能只是说明插图,或者是您的起点。