【问题标题】:AngularJS - Watch for model of transcluded elementAngularJS - 监视嵌入元素的模型
【发布时间】:2013-07-19 09:36:00
【问题描述】:

在 AngularJS 中,我有带有基本嵌入的指令。我知道当我使用它时通常是嵌入的输入或文本区域,如果存在,我想 $watch 其模型以进行更改。但是我无权访问嵌入内容的属性,只能访问调用该指令的根元素的属性。嵌入范围也是如此(也许 scope.$$nextSibling 可以提供帮助,但有些东西告诉我这是通往地狱的路:))。

那么有什么方法可以做到这一点,而无需向调用指令的元素添加另一个参数(属性)?

指令模板

<div ng-transclude>
    <someContent>...</someContent>
    <!-- HERE IS INPUT TRANSCLUDED -->
</div>

指令用法

<div my-directive="somedata">                           //this attribs are accessable
    <input ng-model="iWantToWatchThisInMyDirective" />  //but i want to access this also
</div>

【问题讨论】:

  • 你想达到什么目的??
  • 我想知道模型文本是否为空并应用一些逻辑,例如将类添加到指令的根元素等。
  • 最好的方法是在属性中传递参数 iWantToWatchThisInMyDirective 并观察该属性,但如果你不想这样做,那么你可以在父控制器中观看模型并在父控制器中广播事件并收听指令中的事件
  • @Ajaybeniwal 不错的提示!我还发现 angular.element 提供了 scope() 方法,因此可以通过这种方式访问​​范围。现在只需找出元素中 ngModel / ngBind 的内容 - 充其量是标准化形式的 $attrs,所以我不必尝试每个替代方案(data-ng-model,x-ng-model atc..)..

标签: angularjs angularjs-directive transclusion


【解决方案1】:

这是我的解决方案:

我创建了第二个指令:输入(仅限于元素,因此每个输入都有一个)。在 Input 指令中,我广播了对元素范围的每个更改:

link: function (scope, element: JQuery, attrs: ng.IAttributes) {
  if(typeof attrs.ngModel !== "undefined") {
    scope.$watch(attrs.ngModel, function (newValue, oldValue) {
      scope.$broadcast('valueChanged'+scope.$id, newValue, oldValue);
    });
  }
}

scope.$id 仅用于确保每个输入的事件名称都是唯一的。

现在,在任何其他指令中,我都可以监听更改任何输入的事件:

link: function (scope, element:JQuery, attrs:ng.IAttributes) {
  //My input is last child everytime..
  var children = element.find("input");
  var lastInput = angular.element(children[children.length - 1]); 
  var lastInputScope = lastInput.scope();

  var unregister = lastInputScope.$on('valueChanged' + lastInputScope.$id, 
                                      function (event, newValue, oldValue) {
    //do whatever you want...
  });

  scope.$on('$destroy', function () {
    unregister();
  });
}

【讨论】:

    【解决方案2】:

    这是您可以使用$scope.$watch 执行此操作的另一种方法。这段代码是在没有 jQuery 的情况下编写的。

    angular.module('sample').directive('sampleDirective', function () {
        'use strict';
    
        // Returns a JQLite object for the first input element we transcluded, 
        // allowing us to pick information from it
        function findInput(clone) {
            for (var i = 0; i < clone.length; i++) {
                if (clone[i].nodeName.toLowerCase() == 'input') {
                    return angular.element(clone[i]);
                }
            }
        }
    
        return {
            transclude: true,
            link: function (scope, element, attrs, ctrl, transclude) {
    
                transclude(function (clone) {
                    var input = findInput(clone);
                    if (input) {
    
                        // Watch for changes on our select element's model
                        scope.$watch(input.attr('ng-model'), function (val) {
    
                            // Do things
                            console.log('My updated model:', val);
                        });
                    }
                });
            }
        };
    });
    

    这假设您的模型在指令所在的同一范围内可用。如果您的指令具有隔离作用域,您可以更改 watch 语句以监视 $parent 作用域上的 ng-model 字符串:

    scope.$watch('$parent.' + input.attr('ng-model')

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-26
      • 2016-12-07
      • 2016-03-08
      • 1970-01-01
      • 2014-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多