¿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 .
$broadcastahora evita burbujear sobre ámbitos no registrados y se ejecuta tan rápido como $ emit.Entonces, ahora puedes:
$broadcastde la$rootScope$onel local$scopeque necesita saber sobre el eventoRespuesta original a continuación
Recomiendo no usar
$rootScope.$broadcast+$scope.$onsino 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$scopesea 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$destroyevento 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
$rootScopey darle un$onRootScopeque se suscribe a los eventos emitidos en el$rootScopepero también limpia directamente el controlador cuando el local$scopese destruye.La forma más limpia de parchear el mono
$rootScopepara proporcionar dicho$onRootScopemé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
$onRootScopepropiedad no se muestre inesperadamente al enumerar$scope, usamosObject.defineProperty()y establecemosenumerableenfalse. 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
$broadcasttrae 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
$broadcastde la$rootScope$onel local$scopeque necesita saber sobre el eventoPara publicar
Y suscríbete
Saqueadores
Controller AssintaxisSi registra el oyente en el local
$scope, se destruirá automáticamente por$destroysí mismo cuando se elimine el controlador asociado.fuente
controllerAssintaxis? Pude usar$rootScopeel suscriptor para escuchar el evento, pero tenía curiosidad por saber si había un patrón diferente.$scopeexplí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 Astodavía lo tiene$scope, está justo debajo del capó).controller asalternativa 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
$rootScopey$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,$rootScopeno 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$rootScopedirectamente.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.emitse 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
$rootScopee 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 $broadcastque son responsables de despachar eventos (pueden ser eventos personalizados) y usan la$rootScope.$onfunción para agregar un detector de eventos.fuente
Debe usar el Servicio, ya que
$rootscopees 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