javascript - 如何将 DOM 元素传递给 "ng-disabled"

标签 javascript angularjs dom

全部,

如何将当前 DOM 元素传递给 Angular 指令“ng-disabled”?

我确实知道在 Angular 中搞乱 DOM 是不好的做法。但我想不出另一种简单的方法来做到这一点。这是我的问题:

我有一个按钮,单击时会更新范围变量:

<button ng-click="target_model.display_detail=true">click me</button>

在我的模板中的其他地方有代码监视“target_model.display_detail” - 当它为 true 时,它​​会显示一个模态对话框,其中包含一个 Angular 指令,该指令从服务器获取一些数据并填充一个表单,其中包含另一个按钮如上面的按钮

我正在使用的数据结构可能是递归的;有大量嵌套的“target_models”。因此,模态对话框中的按钮可以指向已创建表单的 target_model。在这种情况下,我只想禁用该按钮。我想做这样的事情:

<button ng-disabled="ancestor_model_exists(the_current_element, target_model.some_unique_id)">click me</button>

其中“ancestor_model_exists”是一个函数,用于检查 DOM 以查看是否存在具有特定 id 的祖先元素。但我如何知道从哪个元素开始呢?

最佳答案

您正在以命令式方式处理 DOM 操作 - jQuery 方式,而不是声明式方式 - Angular 方式。

DOM 操作很好...在指令内。您不会在 Controller 中执行此操作,因为您可能在 Controller 中定义了该函数。

当你有机会时,尝试在沙箱中对 $ 进行 0 次调用,以迫使你学习如何以 Angular 方式做事 - 不是因为它绝对“更好”方式 - 无论如何,在按您的方式操作之前,通常最好先学习工具包和推荐的方法。

这应该做你想要的,除了可能搜索多个祖先之外(但我提到如果你需要的话如何做到这一点):

https://plnkr.co/edit/7O8UDuqsVTlH8r2GoxQu?p=preview

JS

app.directive('ancestorId', function() {
  return {
    restrict: 'A',
    controller: 'AncestorIdController',
    require: ['ancestorId'],
    link: function(scope, element, attrs, controllers) {
      var ancestorIdController = controllers[0];

      // If you wanted to use an expression instead of an 
      // interpolation you could define an isolate scope on this 
      // directive and $watch it.
      attrs.$observe('ancestorId', function(value) {
        ancestorIdController.setId(value);
      });
    }
  }
});

app.controller('AncestorIdController', function() {
  this.getId = _getId;
  this.setId = _setId;

  var id;

  function _getId() {
    return id;
  }

  function _setId(value) {
    id = value;
  }
});

app.directive('disableForAncestorId', function() {
  return {
    restrict: 'A',
    require: ['?^ancestorId'],
    link: function(scope, element, attrs, controllers) {
      var ancestorIdController = controllers[0];

      // Check to make sure the ancestorId is a parent.
      if (ancestorIdController) {
        scope.$watch(function() {
          var watch = {
            target: ancestorIdController.getId(),
            actual: attrs.disableForAncestorId
          };
          return watch;

        }, function(value) {
          if (value.target === value.actual) {
            element.attr('disabled', 'disabled');
          } else {
            element.removeAttr('disabled');
          }
        }, true /* Deep watch */ );
      }
    }
  }
});

HTML

<!-- The simple happy path. -->
<div ancestor-id="A">
  <button disable-for-ancestor-id="A">'A' === 'A' ?</button>
</div>

<!-- require will match the 'B' before the 'A' because it's closer.
 if you need to match any parent you could use a third coordinating
 directive. -->
<div ancestor-id="A">
  <div ancestor-id="B">
    <button disable-for-ancestor-id="A">'B' === 'A' ?</button>
  </div>
</div>

<!-- require lets you freely change the DOM to add extra elements separating
you from what you're looking for.-->
<div ancestor-id="B">
  <div>
    <div>
      <button disable-for-ancestor-id="B">'B' === 'B' ?</button>
    </div>
  </div>
</div>

<!-- It doesn't blow up if it doesn't find an ancestorId. -->
<div>
  <button disable-for-ancestor-id="B">'B' === undefined ?</button>
</div>

<br>
Dynamic AncestorId test (it will be disabled if the text fields are equal):
<br>
Target AncestorId <input ng-model="targetAncestorId">
<br>
Actual Ancestor <input ng-model="actualAncestorId">
<!-- It doesn't blow up if it doesn't find an ancestorId. -->
<div ancestor-id="{{ targetAncestorId }}">
  <button disable-for-ancestor-id="{{ actualAncestorId }}">'{{ actualAncestorId }}' === '{{ actualAncestorId }}' ?</button>
</div>

关于javascript - 如何将 DOM 元素传递给 "ng-disabled",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36587299/

相关文章:

javascript - 扩展对象的 typescript 数组而不修改源

javascript - Protractor 排序基本测试。登录后运行测试

javascript - 带有 angularjs ngoptions 的默认虚拟项目

javascript - 删除处理程序不在范围内的事件监听器

asp.net - jQuery 中的可拖动 UI

javascript - 提交 from,由 ajax 请求处理

javascript - 我可以在 Node 服务器停止后调用 $modal.open

javascript - 查找正在更改 DOM 元素的 javascript

jquery - 单击而不是按钮更改特定行的 CSS

javascript - 防止绑定(bind)到对象的 JavaScript 事件被覆盖