directivas angularjs

angularjs - directivas angular 5



Cómo cancelar la suscripción a un evento de difusión en angularJS. Cómo eliminar la función registrada a través de $ en (8)

''$ on'' devuelve la función para anular el registro

var unregister= $rootScope.$on(''$stateChangeStart'', function(event, toState, toParams, fromState, fromParams, options) { alert(''state changing''); });

puede llamar a la función unregister () para anular el registro de ese oyente

He registrado a mi oyente en un evento $ broadcast usando $ en la función

$scope.$on("onViewUpdated", this.callMe);

y quiero cancelar el registro de este oyente en función de una regla empresarial particular. Pero mi problema es que una vez que está registrado no puedo anular su registro.

¿Hay algún método en AngularJS para anular el registro de un oyente en particular? Un método como $ en la cancelación de este evento, puede ser $ off. Así que basándome en la lógica empresarial puedo decir

$scope.$off("onViewUpdated", this.callMe);

y esta función deja de ser llamada cuando alguien transmite un evento "onViewUpdated".

Gracias

EDITAR : Quiero anular el registro del oyente de otra función. No es la función donde lo registro.


Debe almacenar la función devuelta y llamarla para cancelar la suscripción del evento.

var deregisterListener = $scope.$on("onViewUpdated", callMe); deregisterListener (); // this will deregister that listener

Esto se encuentra en el código fuente :) al menos en 1.0.4. Voy a publicar el código completo ya que es corto

/** * @param {string} name Event name to listen on. * @param {function(event)} listener Function to call when the event is emitted. * @returns {function()} Returns a deregistration function for this listener. */ $on: function(name, listener) { var namedListeners = this.$$listeners[name]; if (!namedListeners) { this.$$listeners[name] = namedListeners = []; } namedListeners.push(listener); return function() { namedListeners[indexOf(namedListeners, listener)] = null; }; },

Además, ver los documentos .


Después de depurar el código, creé mi propia función como la respuesta de "blesh". Así que esto es lo que hice

MyModule = angular.module(''FIT'', []) .run(function ($rootScope) { // Custom $off function to un-register the listener. $rootScope.$off = function (name, listener) { var namedListeners = this.$$listeners[name]; if (namedListeners) { // Loop through the array of named listeners and remove them from the array. for (var i = 0; i < namedListeners.length; i++) { if (namedListeners[i] === listener) { return namedListeners.splice(i, 1); } } } } });

así que al adjuntar mi función a $ rootscope ahora está disponible para todos mis controladores.

y en mi codigo estoy haciendo

$scope.$off("onViewUpdated", callMe);

Gracias

EDITAR: ¡La forma en que AngularJS hace esto está en la respuesta de @LiviuT! Pero si desea desregistrar al oyente en otro ámbito y al mismo tiempo quiere evitar la creación de variables locales para mantener las referencias de la función de desregistro. Esta es una posible solución.


En cuanto a la mayoría de las respuestas, parecen demasiado complicadas. Angular ha incorporado mecanismos para anular el registro.

Utilice la función de desregistro devuelta por $on :

// Register and get a handle to the listener var listener = $scope.$on(''someMessage'', function () { $log.log("Message received"); }); // Unregister $scope.$on(''$destroy'', function () { $log.log("Unregistering listener"); listener(); });


Este código funciona para mí:

$rootScope.$$listeners.nameOfYourEvent=[];


La respuesta de @LiviuT es impresionante, pero parece que muchas personas se preguntan cómo volver a acceder a la función de desmontaje del controlador desde otro $ alcance o función, si desea destruirlo desde un lugar diferente al lugar donde se creó. La respuesta de @ Рустем Мусабеков funciona simplemente bien, pero no es muy idiomática. (Y se basa en lo que se supone que es un detalle de implementación privada, que podría cambiar en cualquier momento). Y a partir de ahí, se vuelve más complicado ...

Creo que la respuesta fácil aquí es simplemente llevar una referencia a la función de offCallMeFn ( offCallMeFn en su ejemplo) en el controlador en sí, y luego llamarlo en función de alguna condición; Tal vez un argumento que incluya en el evento que emite o emita. De este modo, los manipuladores pueden derrumbarse a sí mismos, cuando lo deseen, donde lo deseen, transportando las semillas de su propia destrucción. Al igual que:

// Creation of our handler: var tearDownFunc = $rootScope.$on(''demo-event'', function(event, booleanParam) { var selfDestruct = tearDownFunc; if (booleanParam === false) { console.log(''This is the routine handler here. I can do your normal handling-type stuff.'') } if (booleanParam === true) { console.log("5... 4... 3... 2... 1...") selfDestruct(); } }); // These two functions are purely for demonstration window.trigger = function(booleanArg) { $scope.$emit(''demo-event'', booleanArg); } window.check = function() { // shows us where Angular is stashing our handlers, while they exist console.log($rootScope.$$listeners[''demo-event'']) }; // Interactive Demo: >> trigger(false); // "This is the routine handler here. I can do your normal handling-type stuff." >> check(); // [function] (So, there''s a handler registered at this point.) >> trigger(true); // "5... 4... 3... 2... 1..." >> check(); // [null] (No more handler.) >> trigger(false); // undefined (He''s dead, Jim.)

Dos pensamientos

  1. Esta es una gran fórmula para un controlador de ejecución única. Simplemente suelte los condicionales y ejecute selfDestruct tan pronto como haya completado su misión suicida.
  2. Me pregunto si el ámbito de origen se destruirá correctamente y se recogerá basura, dado que está llevando referencias a variables cerradas. Tendrías que usar un millón de estos para que sea un problema de memoria, pero tengo curiosidad. Si alguien tiene alguna idea, por favor comparta.

Una forma es simplemente destruir al oyente una vez que haya terminado con él.

var removeListener = $scope.$on(''navBarRight-ready'', function () { $rootScope.$broadcast(''workerProfile-display'', $scope.worker) removeListener(); //destroy the listener })


EDITAR: ¡La forma correcta de hacer esto está en la respuesta de @LiviuT!

Siempre puede ampliar el alcance de Angular para permitirle eliminar tales escuchas de esta manera:

//A little hack to add an $off() method to $scopes. (function () { var injector = angular.injector([''ng'']), rootScope = injector.get(''$rootScope''); rootScope.constructor.prototype.$off = function(eventName, fn) { if(this.$$listeners) { var eventArr = this.$$listeners[eventName]; if(eventArr) { for(var i = 0; i < eventArr.length; i++) { if(eventArr[i] === fn) { eventArr.splice(i, 1); } } } } } }());

Y así es como funcionaría:

function myEvent() { alert(''test''); } $scope.$on(''test'', myEvent); $scope.$broadcast(''test''); $scope.$off(''test'', myEvent); $scope.$broadcast(''test'');

Y aquí hay un plunker en acción.