【问题标题】:How to create a custom angular directive that will override ng-disabled?如何创建将覆盖 ng-disabled 的自定义角度指令?
【发布时间】:2015-07-16 14:05:57
【问题描述】:

首先是一些背景知识:我的应用程序允许用户通过管理工具控制是否需要、禁用等字段。我有一个服务,它接受一个字段名称并以如下格式返回用户定义的规则:

{
  "disabled" : true,
  "required" : true
}

我想要一个自定义属性指令,该指令将使用该服务控制输入字段上的这些属性。我希望用法看起来像这样:

<input type="text" my-rule="fieldName" ng-model="myfield" />

我可以使用如下指令轻松完成此操作:

angular.module('app').directive('myRule', ['$http',
  function($http) {
    return {
      restrict: 'A',
      scope: {
        myRule: '@'
      },
      link: function(scope, element, attrs) {
        $http.get('/api/rule/'+scope.myRule).success(function(rule) {
          if (rule.disabled) {
            element.attr('disabled','disabled');
          }
          if (rule.required) {
            element.attr('required','required');
          }
        });
      }
    }
  }
]);

我的问题是,如果用户没有禁用某个字段,我可能仍想禁用它,直到例如另一个字段被填写为止。使用ng-disabled 应该很容易做到这一点:

<input type="text" my-rule="fieldA" ng-model="fieldA" />
<input type="text" my-rule="fieldB" ng-model="fieldB" ng-disabled="!fieldA" />

但是,这不起作用,因为如果用户选择禁用fieldB,则无论ng-disabled 属性如何,都应始终禁用该字段,而是ng-disabled 属性覆盖用户的规则。如果该字段被用户禁用但似乎没有效果,我尝试了这样的方法来删除 ng-disabled

angular.module('app').directive('myRule', ['$http',
  function($http) {
    return {
      restrict: 'A',
      scope: {
        myRule: '@'
      },
      link: function(scope, element, attrs) {
        $http.get('/api/rule/'+scope.myRule).success(function(rule) {
          if (rule.disabled) {
            element.attr('disabled','disabled');
            element.removeAttr('ng-disabled');
          }
          if (rule.required) {
            element.attr('required','required');
            element.removeAttr('ng-required');
          }
        });
      }
    }
  }
]);

这会删除该属性,但似乎为时已晚,只要填写了fieldA,该字段仍然会启用。

如何动态删除自定义指令中的ng-disabled 属性,使其不再对该字段产生影响?

更新:

我添加了一个代码 sn-p 来演示我的问题。

    angular.module('app',[]).directive('myRule', ['$http',
      function($http) {
        return {
          restrict: 'A',
          scope: {
            myRule: '@'
          },
          link: function(scope, element, attrs) {
            // would normally be making an ajax call to get the rule
            var rule = { disabled: scope.myRule != "fieldA" };

            if (rule.disabled) {
              element.attr('disabled','disabled');
              element.removeAttr('ng-disabled');
            }
          }
        }
      }
    ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="app">
  <p>Field B and Field C have been disabled by the user but since Field C includes an ng-disabled expression it will be incorrectly enabled when Field A is filled out.</p>
  <input type="text" my-rule="fieldA" ng-model="fieldA" placeholder="Field A" />
  <input type="text" my-rule="fieldB" ng-model="fieldB" placeholder="Field B" />
  <input type="text" my-rule="fieldC" ng-model="fieldC" placeholder="Field C" ng-disabled="!fieldA" />
</div>

【问题讨论】:

  • 您是否尝试创建优先级高于ng-disabled 的指令? (ngDisabled 优先级为 100)也许会有所帮助。
  • 我确实尝试过,但原来的 ng-disabled 仍然覆盖了用户规则。
  • 嘿@Kyle 你找到解决方案了吗,我有类似的问题并且没有找到解决方案。如果你想通了,请帮助我,谢谢
  • 嘿@Kyle 我刚刚找到了解决方案,$attrs.$set('disabled', 'disabled');

标签: javascript angularjs


【解决方案1】:

试试prop('disabled', boolean) 而不是attr()。这将更改元素属性,该属性并不总是与属性相同。

由于您在 Angular 之外操作 DOM,您可能应该通过调用 scope.$apply()$timeout() 来告诉 Angular 运行摘要

不确定这是否可行,我认为您可能需要一个指令来包装整个输入。

一个建议是看看angular-formly,它构建了整个表单,包括来自对象模型的条件验证

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-24
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    相关资源
    最近更新 更多