I want to create a publish/subscribe mechanism with angular event system.
我想创建一个具有角度事件系统的发布/订阅机制。
angular.module("app",[]);
angular.module("app").directive("first", function($rootScope){
return {
template: "First Directive",
link:function(scope,element,attribute){
$rootScope.$broadcast("OnFirstDirectiveCreated", {
"message": "I'm first directive"
});
}
}
})
angular.module("app").directive("second", function($rootScope){
return {
template: "Second Directive",
link:function(scope,element,attribute){
var handler = $rootScope.$on("OnFirstDirectiveCreated",
function (event, args) {
console.log("First Directive Message: " + args.message);
});
}
}
})
if I set HTML document like this, no message appear in console:
如果我设置这样的HTML文档,控制台不会显示消息:
<div ng-app="app">
<first></first>
<second></second>
</div>
If I change order first and second, message wirite on console.
如果我改变顺序,第一和第二,消息wirite在控制台。
<div ng-app="app">
<second></second>
<first></first>
</div>
But I need first directive or inner directive.
但我需要第一指令或内在指令。
<div ng-app="app">
<first></first>
<second></second>
</div>
<div ng-app="app">
<first>
<second></second>
</first>
</div>
I tried both $rootScope.$broadcast
and $rootScope.$emit
but did not woeked.
我试着rootScope美元。广播和rootScope美元。$emit但并没有消散。
演示工作
2 个解决方案
#1
4
It's absolutely correct angular behavior.
这绝对是正确的角度行为。
In the first example:
在第一个例子:
<first></first>
<second></second>
Angular creates a directive for first
tag and sends event immediately, but the second directive is not created yet.
角为第一个标记创建一个指令并立即发送事件,但是第二个指令还没有创建。
In the second example:
在第二个例子中:
<first></first>
<second></second>
Here you firstly subscribe to an event, and after that first
directive sends a message. Because of this, second
directive accepts an event.
在这里,您首先订阅事件,然后在第一个指令发送消息。因此,第二个指令接受事件。
Third example:
第三个例子:
<first>
<second></second>
</first>
This case, as well as the first example won't be working.
这个例子和第一个例子都不会起作用。
Solution: One of solutions is to set timeout in first directive to don't send event immediately after creation. If the second parameter of $timeout
, delay
is not provided, the default behaviour is to execute the function after the DOM has completed rendering:
解决方案:一种解决方案是在第一个指令中设置超时,以避免在创建后立即发送事件。如果第二个参数是$timeout,没有提供delay,默认行为是在DOM完成渲染后执行函数:
angular.module("app").directive("first", function($rootScope, $timeout) {
return {
template: "First Directive",
link: function(scope,element,attribute) {
$timeout(function() {
$rootScope.$broadcast("OnFirstDirectiveCreated", {
"message": "I'm first directive"
})
});
}
}
});
演示
#2
1
This happens because when broadcast of first directive is executed, the second directive is not ready and therefore the signal is lost and communication does not happen. One way of solving it, is to send the signal many times using $interval function and stop transmitting only when the second directive is ready. Of course the second directive has to broadcast back when it receives data from the first. The second solution, for which I would go, is for the second directive to notify when its ready to the first directive by broadcasting with $rootScope in a similar fashion as you did in first directive.
这是因为当执行第一个指令的广播时,第二个指令没有准备好,因此信号丢失,通信没有发生。一种解决方法是使用$interval函数多次发送信号,只有在第二个指令就绪时才停止传输。当然,第二个指令必须在接收到第一个指令的数据时进行广播。第二个解决方案,我要讲的是,第二个指令在准备好第一个指令时通知它,使用$rootScope进行广播,方式与你在第一个指令中所做的类似。
angular.module("app").directive("second", function($rootScope){
return {
template: "Second Directive",
link:function(scope,element,attribute){
var handler = $rootScope.$on("secondDirective",
function (event, args) {
console.log("First Directive Data: " + args);
});
$rootScope.$broadcast("OnChildDirectiveCreated", {
"message": "I'm second directive",
"id": "secondDirective"
});
}
}
})
and the first directive:
和第一个指令:
angular.module("app").directive("first", function($rootScope){
return {
template: "First Directive",
link:function(scope,element,attribute){
$rootScope.$on("OnChildDirectiveCreated", function(event, args) {
$rootScope.$broadcast(args.id, someData);
});
}
}
})
Since you are using a parent child structure, it is always guaranteed that the first directive will be ready when child directives are ready. Using this solution you could use many child directives. Hope this helps!
由于您正在使用父子结构,所以总是可以保证在子指令准备好时,第一个指令将准备好。使用这个解决方案,您可以使用许多子指令。希望这可以帮助!
#1
4
It's absolutely correct angular behavior.
这绝对是正确的角度行为。
In the first example:
在第一个例子:
<first></first>
<second></second>
Angular creates a directive for first
tag and sends event immediately, but the second directive is not created yet.
角为第一个标记创建一个指令并立即发送事件,但是第二个指令还没有创建。
In the second example:
在第二个例子中:
<first></first>
<second></second>
Here you firstly subscribe to an event, and after that first
directive sends a message. Because of this, second
directive accepts an event.
在这里,您首先订阅事件,然后在第一个指令发送消息。因此,第二个指令接受事件。
Third example:
第三个例子:
<first>
<second></second>
</first>
This case, as well as the first example won't be working.
这个例子和第一个例子都不会起作用。
Solution: One of solutions is to set timeout in first directive to don't send event immediately after creation. If the second parameter of $timeout
, delay
is not provided, the default behaviour is to execute the function after the DOM has completed rendering:
解决方案:一种解决方案是在第一个指令中设置超时,以避免在创建后立即发送事件。如果第二个参数是$timeout,没有提供delay,默认行为是在DOM完成渲染后执行函数:
angular.module("app").directive("first", function($rootScope, $timeout) {
return {
template: "First Directive",
link: function(scope,element,attribute) {
$timeout(function() {
$rootScope.$broadcast("OnFirstDirectiveCreated", {
"message": "I'm first directive"
})
});
}
}
});
演示
#2
1
This happens because when broadcast of first directive is executed, the second directive is not ready and therefore the signal is lost and communication does not happen. One way of solving it, is to send the signal many times using $interval function and stop transmitting only when the second directive is ready. Of course the second directive has to broadcast back when it receives data from the first. The second solution, for which I would go, is for the second directive to notify when its ready to the first directive by broadcasting with $rootScope in a similar fashion as you did in first directive.
这是因为当执行第一个指令的广播时,第二个指令没有准备好,因此信号丢失,通信没有发生。一种解决方法是使用$interval函数多次发送信号,只有在第二个指令就绪时才停止传输。当然,第二个指令必须在接收到第一个指令的数据时进行广播。第二个解决方案,我要讲的是,第二个指令在准备好第一个指令时通知它,使用$rootScope进行广播,方式与你在第一个指令中所做的类似。
angular.module("app").directive("second", function($rootScope){
return {
template: "Second Directive",
link:function(scope,element,attribute){
var handler = $rootScope.$on("secondDirective",
function (event, args) {
console.log("First Directive Data: " + args);
});
$rootScope.$broadcast("OnChildDirectiveCreated", {
"message": "I'm second directive",
"id": "secondDirective"
});
}
}
})
and the first directive:
和第一个指令:
angular.module("app").directive("first", function($rootScope){
return {
template: "First Directive",
link:function(scope,element,attribute){
$rootScope.$on("OnChildDirectiveCreated", function(event, args) {
$rootScope.$broadcast(args.id, someData);
});
}
}
})
Since you are using a parent child structure, it is always guaranteed that the first directive will be ready when child directives are ready. Using this solution you could use many child directives. Hope this helps!
由于您正在使用父子结构,所以总是可以保证在子指令准备好时,第一个指令将准备好。使用这个解决方案,您可以使用许多子指令。希望这可以帮助!