¿Cuál es la forma correcta de comunicarse entre los controladores?
Actualmente estoy usando un horrible dulce de azúcar que involucra window
:
function StockSubgroupCtrl($scope, $http) {
$scope.subgroups = [];
$scope.handleSubgroupsLoaded = function(data, status) {
$scope.subgroups = data;
}
$scope.fetch = function(prod_grp) {
$http.get('/api/stock/groups/' + prod_grp + '/subgroups/').success($scope.handleSubgroupsLoaded);
}
window.fetchStockSubgroups = $scope.fetch;
}
function StockGroupCtrl($scope, $http) {
...
$scope.select = function(prod_grp) {
$scope.selectedGroup = prod_grp;
window.fetchStockSubgroups(prod_grp);
}
}
Respuestas:
Editar : El problema abordado en esta respuesta se ha resuelto en angular.js versión 1.2.7 .
$broadcast
ahora evita burbujear sobre ámbitos no registrados y se ejecuta tan rápido como $ emit.Entonces, ahora puedes:
$broadcast
de la$rootScope
$on
el local$scope
que necesita saber sobre el eventoRespuesta original a continuación
Recomiendo no usar
$rootScope.$broadcast
+$scope.$on
sino más bien$rootScope.$emit
+$rootScope.$on
. El primero puede causar serios problemas de rendimiento como lo plantea @numan. Esto se debe a que el evento burbujeará en todos los ámbitos.Sin embargo, este último (usando
$rootScope.$emit
+$rootScope.$on
) no sufre esto y, por lo tanto, puede usarse como un canal de comunicación rápido.De la documentación angular de
$emit
:Como no hay un alcance arriba
$rootScope
, no hay burbujeo. Es totalmente seguro usar$rootScope.$emit()
/$rootScope.$on()
como EventBus.Sin embargo, hay un problema al usarlo desde Controladores. Si se vincula directamente
$rootScope.$on()
desde dentro de un controlador, tendrá que limpiar el enlace usted mismo cuando su local$scope
sea destruido. Esto se debe a que los controladores (en contraste con los servicios) pueden instanciarse varias veces durante la vida útil de una aplicación, lo que daría como resultado que los enlaces se sumen y eventualmente creen pérdidas de memoria por todas partes :)Para cancelar el registro, simplemente escuchar en su
$scope
's$destroy
evento y luego llamar a la función que devolvió$rootScope.$on
.Diría que eso no es realmente algo angular específico, ya que también se aplica a otras implementaciones de EventBus, que tienes que limpiar los recursos.
Sin embargo, puede facilitarle la vida en esos casos. Por ejemplo, podría mono parchear
$rootScope
y darle un$onRootScope
que se suscribe a los eventos emitidos en el$rootScope
pero también limpia directamente el controlador cuando el local$scope
se destruye.La forma más limpia de parchear el mono
$rootScope
para proporcionar dicho$onRootScope
método sería a través de un decorador (un bloque de ejecución probablemente también funcionará bien, pero pssst, no se lo digas a nadie)Para asegurarnos de que la
$onRootScope
propiedad no se muestre inesperadamente al enumerar$scope
, usamosObject.defineProperty()
y establecemosenumerable
enfalse
. Tenga en cuenta que es posible que necesite una cuña ES5.Con este método, el código del controlador de arriba se puede simplificar para:
Como resultado final de todo esto, le recomiendo que use
$rootScope.$emit
+$scope.$onRootScope
.Por cierto, estoy tratando de convencer al equipo angular para abordar el problema dentro del núcleo angular. Hay una discusión aquí: https://github.com/angular/angular.js/issues/4574
Aquí hay un jsperf que muestra cuánto impacto de rendimiento
$broadcast
trae a la mesa en un escenario decente con solo 100$scope
's.http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
fuente
La respuesta superior aquí fue una solución a un problema angular que ya no existe (al menos en las versiones> 1.2.16 y "probablemente anterior") como ha mencionado @zumalifeguard. Pero me quedo leyendo todas estas respuestas sin una solución real.
Me parece que la respuesta ahora debería ser
$broadcast
de la$rootScope
$on
el local$scope
que necesita saber sobre el eventoPara publicar
Y suscríbete
Saqueadores
Controller As
sintaxisSi registra el oyente en el local
$scope
, se destruirá automáticamente por$destroy
sí mismo cuando se elimine el controlador asociado.fuente
controllerAs
sintaxis? Pude usar$rootScope
el suscriptor para escuchar el evento, pero tenía curiosidad por saber si había un patrón diferente.$scope
explícitamente. John Papa escribe sobre los eventos como una "excepción" a su regla habitual de mantener$scope
"fuera" de sus controladores (uso citas porque, como él menciona,Controller As
todavía lo tiene$scope
, está justo debajo del capó).controller as
alternativa de sintaxis según lo solicitado. Espero que sea lo que quisiste decir.Usando $ rootScope. $ Broadcast y $ scope. $ On para una comunicación PubSub.
Además, vea esta publicación: AngularJS: comunicación entre controladores
fuente
$rootScope
y$watch
. No estoy seguro de que eso sea una mejora.Dado que defineProperty tiene un problema de compatibilidad del navegador, creo que podemos pensar en usar un servicio.
y úsalo en un controlador como este:
controlador 1
controlador 2
fuente
GridLinked publicó una solución PubSub que parece estar diseñada bastante bien. El servicio se puede encontrar, aquí .
También un diagrama de su servicio:
fuente
En realidad, el uso de emitir y emitir es ineficiente porque el evento sube y baja en la jerarquía del alcance, lo que puede degradarse fácilmente en una botella de rendimiento para una aplicación compleja.
Sugeriría utilizar un servicio. Así es como lo implementé recientemente en uno de mis proyectos: https://gist.github.com/3384419 .
Idea básica: registrar un pub / club de eventos como servicio. Luego inyecte ese bus de eventos donde necesite suscribirse o publicar eventos / temas.
fuente
$rootScope.$emit()
solo burbujea hacia arriba. Sin embargo, como no hay un alcance superior,$rootScope
no hay nada que temer. Entonces, si solo está usando$rootScope.$emit()
y$rootScope.$on()
tendrá un EventBus rápido en todo el sistema.$rootScope.$on()
dentro de su controlador, deberá limpiar el enlace del evento, ya que de lo contrario se resumirán, ya que se crea uno nuevo cada vez que se crea una instancia del controlador y no lo hacen. ser destruido automáticamente por usted ya que está vinculado$rootScope
directamente.Usando métodos get y set dentro de un servicio, puede pasar mensajes entre controladores muy fácilmente.
en HTML HTML puedes marcar así
fuente
Con respecto al código original, parece que desea compartir datos entre ámbitos. Para compartir datos o estados entre $ scope, los documentos sugieren usar un servicio:
Ref: Enlace de Documentos Angulares aquí
fuente
De hecho, comencé a usar Postal.js como un bus de mensajes entre controladores.
Tiene muchos beneficios como bus de mensajes, como los enlaces de estilo AMQP, la forma en que postal puede integrarse con iFrames y sockets web, y muchas cosas más.
Utilicé un decorador para configurar Postal en
$scope.$bus
...Aquí hay un enlace a una publicación de blog sobre el tema ...
http://jonathancreamer.com/an-angular-event-bus-with-postal-js/
fuente
Así es como lo hago con Factory / Services y la inyección de dependencia simple (DI) .
fuente
Me gustó la forma en que
$rootscope.emit
se utilizó para lograr la intercomunicación. Sugiero la solución limpia y efectiva de rendimiento sin contaminar el espacio global.fuente
Aquí está la manera rápida y sucia.
Aquí hay una función de ejemplo para agregar dentro de cualquiera de los controladores hermanos:
y, por supuesto, aquí está tu HTML:
fuente
$rootScope
?Iniciando angular 1.5 y su enfoque de desarrollo basado en componentes. La forma recomendada para que los componentes interactúen es mediante el uso de la propiedad 'require' y mediante enlaces de propiedades (entrada / salida).
Un componente requeriría otro componente (por ejemplo, el componente raíz) y obtendría una referencia a su controlador:
Luego puede usar los métodos del componente raíz en su componente hijo:
Esta es la función del controlador del componente raíz:
Aquí hay una descripción arquitectónica completa: Comunicaciones de componentes
fuente
Puede acceder a esta función de saludo desde cualquier lugar del módulo
Controlador uno
segundo controlador
Más información aquí.
fuente
Crearé un servicio y usaré notificaciones.
Como en cualquier momento, el Servicio de notificaciones es único, debería poder proporcionar datos persistentes.
Espero que esto ayude
fuente
Puede usar el servicio incorporado AngularJS
$rootScope
e inyectar este servicio en sus dos controladores. Luego puede escuchar los eventos que se activan en el objeto $ rootScope.$ rootScope proporciona dos despachadores de eventos llamados
$emit and $broadcast
que son responsables de despachar eventos (pueden ser eventos personalizados) y usan la$rootScope.$on
función para agregar un detector de eventos.fuente
Debe usar el Servicio, ya que
$rootscope
es el acceso desde toda la Aplicación, y aumenta la carga, o puede usar los parámetros raíz si sus datos no son más.fuente
fuente
Puede hacerlo utilizando eventos angulares que son $ emit y $ broadcast. Según nuestro conocimiento, esta es la mejor manera, eficiente y efectiva.
Primero llamamos a una función desde un controlador.
También puede usar $ rootScope en lugar de $ scope. Use su controlador en consecuencia.
fuente