AngularJS指令广播问题

时间:2015-09-03 13:34:00

标签: angularjs

我有这个指令(我将为了简洁而减少):

.directive('simpleConfigurator', function () {

    return {
        restrict: 'A',
        scope: {
            garment: '=simpleConfigurator',
            colours: '=',
            onComplete: '&'
        },
        require: ['designs', 'colours'],
        transclude: true,
        templateUrl: '/assets/tpl/directives/kit.html',
        link: function (scope, element, attrs, controllers) {

            scope.svgPath = 'assets/garments/' + scope.garment.slug + '.svg';

            // Executes after the svg has loaded
            scope.loaded = function () {

                scope.$broadcast('loaded', { loaded: true });
            };
        }
    };
})

HTML的内容如下所示:

<div ng-transclude></div>
<div id="{{ garment.slug }}" ng-include="svgPath" onload="loaded()"></div>

我试图让它与其他指令进行通信。所以在我的设计指令中,我有这个:

.directive('designs', function () {
    return {
        restrict: 'A',
        controller: 'ConfiguratorDesignsDirectiveController',
        link: function (scope) {

            scope.$on('loaded', function () {

                console.log('we have loaded');
            });
        }
    }
})

我希望我能得到一个控制台日志,说明我们已经加载,但我没有。我认为这是因为两个&#34;设计&#34;和&#34;颜色&#34;被视为父母,孩子是要求的指示。

我是否可以通过其他方式与父指令进行通信,还是有办法让它工作?

4 个答案:

答案 0 :(得分:1)

您有几个选择:

您可以注入$rootScope,并从那里进行广播。虽然这应该有用,但这不是我的第一选择。

您还可以在父指令上使用控制器,并将其作为通信媒介传递给子指令。看起来你已经有了控制器设置。因此,不要在指令中使用$on,为什么不一起放弃事件。只需在控制器上调用一个函数即可。

这也是绝对相关的:What's the correct way to communicate between controllers in AngularJS?

答案 1 :(得分:0)

此处可能存在的另一个问题是simpleConfigurator之前会呈现designs。因此,在设置任何听众之前广播该事件。

您可以尝试在子指令中要求父指令,然后您就可以访问父控制器:

simpleConfigurator

return {
   restrict : 'E',
   require : '^designs',
   link : function (scope, elem, attrs, designsController) {
        designsController.doStuff();
   }
}

designs

return {
   restrict : 'E',
   controller : function ($scope) {
       $scope.doStuff = function () {
           // do some stuff
       }
   }
};

答案 2 :(得分:0)

注入$rootScope并使用$rootScope.$broadcast我相信您正在尝试做的事情,尽管这不是理想的解决方案。

最好在父控制器和指令之间使用一种形式的pub / sub体系结构,然后使用控制器中的$rootScope

您始终可以将事件名称传递给您可以通过属性侦听的指令。利用$scope.$emit$scope.$on来实现您的工作效果。

这将促进DRY原则,旨在使您的指令在您的应用程序中更通用和可重用,这是一般指令的意图之一。

希望能帮到你!

答案 3 :(得分:0)

您的simpleConfigurator指令有自己的隔离范围。您可以使用console.log(scope)查看simpleConfiguratordesign指令的范围是不同的。因此,当您从simpleConfigurator广播时,它永远不会到达design。这是一篇详细解释这一点的文章。

http://www.bennadel.com/blog/2725-how-scope-broadcast-interacts-with-isolate-scopes-in-angularjs.htm

如何在指令之间进行通信 - 我发现这篇文章非常有用。 http://blog.dudak.me/2014/angular-js-directive-communication-guide-part-1/
在您的情况下,您可以使用此策略 -

app.directive("server", function() {
  return {
    controller: function() {
      this.log = function(message) {
        console.log(message);
      };
    }
  };
});

app.directive("client", function() {
  return {
    require: "^server",
    link: function($scope, $elem, $attrs, serverCtrl) {
      serverCtrl.log("Hello, this is the client!");
    }
  };
});

您可能希望在链接函数中使用DOM load事件 - 当资源及其相关资源已完成加载时会触发load事件。

elem.addEventListener('load', callbackFunction, false)