2

在 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>
4

2 回答 2

0

这是我的解决方案:

我创建了第二个指令:输入(仅限于元素,因此每个输入都有一个)。在 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();
  });
}
于 2013-07-26T09:12:48.350 回答
0

这是您可以使用的另一种方法$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 语句以监视范围内的ng-model字符串$parent

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

于 2015-09-01T22:00:33.393 回答