AngularJS - 观察被剔除元素的模型

时间:2013-07-19 09:36:00

标签: angularjs angularjs-directive transclusion

在AngularJS中,我有基本的翻译指令。我知道当我使用它时通常是被抄写的输入或textarea,如果在那里,我想要观察其模型的变化。但我无法访问被转换内容的属性,只能访问调用指令的根元素的属性。被转换的范围(也许范围。$$ 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>

2 个答案:

答案 0 :(得分:0)

这是我的解决方案:

我创建了第二个指令:输入(限制为Ele​​ment,所以每个输入都有一个)。在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);
    });
  }
}

范围。$ 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();
  });
}

答案 1 :(得分:0)

Here's another way you can do this using $scope.$watch. This code is written without 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);
                    });
                }
            });
        }
    };
});

This assumes your model is available on the same scope the directive is on. If your directive has an isolate scope, you could alter the watch statement to watch for the ng-model string on the $parent scope:

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