繁体   English   中英

如何将DOM元素传递给“ ng-disabled”

[英]How to pass a DOM element to “ng-disabled”

所有,

如何将当前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的祖先元素的函数。 但是我怎么知道从哪个元素开始呢?

您必须以jQuery方式而不是以声明方式-Angular方式来强制执行DOM操作。

DOM操作很好...内部指令。 您不必在可能定义了该功能的控制器中执行此操作。

如果有机会,请尝试在沙箱中以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>

它永远不会失败...在Stack Overflow上发布问题总是让我在几分钟后意识到答案。

以下代码使我非常接近:

template.html:

<button ng-click="display_if_ancestor_model_exists($event, target_model)">click me</button>

app.js:

$scope.display_if_ancestor_model_exists = function($event, target_model) {
  var ancestor_form = $($event.target).closest("#" + target_model.some_unique_id);
  if (ancestor_form.length) {
    /* don't show the modal-dialog */
    display_msg("This form already exists!");
  }
  else {
    target_model.display_detail = true;
  }
};

当然,我宁愿只是禁用按钮,但暂时可以使用此解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM