【问题标题】:call function in isolated scope of a directive from another directive在与另一个指令隔离的指令范围内调用函数
【发布时间】:2014-04-22 18:33:30
【问题描述】:

简单地说,我想从另一个指令访问一个指令的隔离范围。

$(element).scope() 似乎返回父范围,而不是隔离范围。下面的描述有点罗嗦所以这里是一个plunkr http://plnkr.co/edit/bG5JW5Ky0K3aTj8gTSsh?p=preview

下面的 html 显示了我有一个 keydown 事件委托的指令和另一个指令,它显示了当突出显示该元素时按下“向下”箭头键时我想要执行的代码。

<body ng-controller="MainCtrl">
<div id="page1" tabindex="-1" key-handler>
<a href="" id="testAnchor" class="highlight" on-down="API.setTarget('section0')">HIGHLIGHTED</a>
</div>
</body>

两个指令共享以下测试控制器

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {

    // this API is injected as a service in the real code
    $scope.API = {};
    $scope.API.setTarget = function ( value ) {
    alert ( "$scope.API.setTarget " + value );
    return true;
  };                  
})

下面的“on-down”指令旨在可重用并允许事件委托器执行“on-down”表达式中包含的函数。作为测试,我在链接函数中调用它以表明它符合我的预期。

.directive ( 'onDown', [ function (  ) {

return {

    restrict: 'A',
    scope: {
        'action': '&onDown'
    },

    link: function ( scope, element, attr ) {           
        // test call when the directive is created to show that it works
        scope.action ( );           
    }
}
}])

但是,当我尝试从另一个指令访问隔离作用域以便执行该代码时,将返回父作用域。

.directive ( 'keyHandler', [

function ( ) {

    return {

              restrict: 'A',                    
              scope: {},

        link: function ( $scope, $element, $attr ) {

            $scope.$on('$destroy', function () {
                $element.unbind ( 'keydown' );
            });

            $element.bind ( 'keydown', function ( event ) {

                e = event || window.event;

                if ( e.stopPropagation ) e.stopPropagation ( );
                if ( e.preventDefault ) e.preventDefault ( );

                var target = e.target || e.srcElement;

                var keyCode = e.keyCode;

                // find all highlighted elements
                var highlightedEl = $('.highlight')[0];
                alert ( "highlightedEl " + $(highlightedEl).attr('id'));

                switch ( keyCode ) {

                case 40:
                  alert ( "down key pressed");
                              var downHandler = $(highlightedEl).attr('on-down');
                              if ( downHandler ) {
                                alert ( "found down handler");
                                  // trigger the function in the highlighted elements isolated scope
                                  // NOTE: targetScope seems to point to the controller scope rather than the highlighted elements isolated scope
                                  var targetScope = $(highlightedEl).scope();
                                  targetScope.action();
                              }
                  break;
                }
            });

          // give focus to this element so it receives all key events
          $scope.$evalAsync ( function ( ) {
            $element[0].focus();                        
          });               
        }
    }
}
]);

【问题讨论】:

  • 我刚刚发现了isolateScope(),它似乎可以满足我的要求。

标签: angularjs


【解决方案1】:

我知道解决此问题的最佳方法是使用控制器在指令之间共享信息。

您创建了一个指令,其中包含一个控制器,该控制器具有可用于传递数据的方法。然后,您创建使用 Require: 作为主指令的其他指令,并在子指令中链接:以连接并调用“父”指令上的方法...

app
  .directive('parentDirective', function(){
     return { 
              restrict: 'E', 
              replace: true,
              template: "<button ng-click='doSomething()'>Do something</button>",
              controller: function($scope) {
                   var somethingsToDo = ['something'];
                   $scope.doSomething = function() {
                          alert(somethingToDo.join());
                   }
                   this.addSomethingToDo = function(somethingToDo) {
                       somethingsToDo.push(somethingToDo);
                   }
             }
       };
  })
  .directive('nothingToDo', function() {
       return {
                restrict: 'A',
                require: 'parentDirective',
                link: function(scope, element, attrs, controller) {
                controller.addSomethingToDo('Nothing');
                }
              }
         }
  });

【讨论】:

  • 谢谢。这就是我正在做的事情。 scope.action() 被映射到在控制器中设置的 API.setTarget()。调用 element.isolateScope() 而不是 element.scope() 似乎给了我正确的范围,我需要在指令中调用 scope.action(),它映射到父控制器中的 API.setTarget()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多