如何创建将覆盖 ng-disabled 的自定义角度指令?

Kyl*_*yle 5 javascript angularjs

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

{
  "disabled" : true,
  "required" : true
}
Run Code Online (Sandbox Code Playgroud)

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

<input type="text" my-rule="fieldName" ng-model="myfield" />
Run Code Online (Sandbox Code Playgroud)

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

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');
          }
        });
      }
    }
  }
]);
Run Code Online (Sandbox Code Playgroud)

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

<input type="text" my-rule="fieldA" ng-model="fieldA" />
<input type="text" my-rule="fieldB" ng-model="fieldB" ng-disabled="!fieldA" />
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,因为如果用户选择禁用,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');
          }
        });
      }
    }
  }
]);
Run Code Online (Sandbox Code Playgroud)

这将删除该属性,但此时似乎为时已晚,并且该字段fieldA在填写后仍会立即启用。

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

更新:

我添加了一个代码片段来演示我的问题。

{
  "disabled" : true,
  "required" : true
}
Run Code Online (Sandbox Code Playgroud)
<input type="text" my-rule="fieldName" ng-model="myfield" />
Run Code Online (Sandbox Code Playgroud)

cha*_*tfl 2

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

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

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

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