Escuchando cambios variables en JavaScript

462

¿Es posible tener un evento en JS que se dispara cuando cambia el valor de una determinada variable? JQuery es aceptado.

rashcroft22
fuente
@BenjaminGruenbaum probablemente quieras decir MutableObserver (para DOM). El objeto es solo para objetos JS de lo que recuerdo.
HellBaby
2
@HellBaby, esta pregunta es sobre variables, no sobre el DOM.
Benjamin Gruenbaum
99
@BenjaminGruenbaum según developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Object.observe está obsoleto o en desuso. El reemplazo recomendado (por esa misma página) es el objeto Proxy.
stannius
44
La pregunta solo pregunta variable, pero todas las respuestas aquí se refieren property. Sin local variableembargo, me pregunto si podemos escuchar los cambios.
Thariq Nugrohotomo
1
¿hay alguna respuesta para esto? Quiero decir, para seleccionar uno
Braian Mellor

Respuestas:

100

Sí, esto ahora es completamente posible!

Sé que este es un subproceso antiguo, pero ahora este efecto es posible utilizando accesores (getters y setters): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters

Puede definir un objeto como este, en el que aInternalrepresenta el campo a:

x = {
  aInternal: 10,
  aListener: function(val) {},
  set a(val) {
    this.aInternal = val;
    this.aListener(val);
  },
  get a() {
    return this.aInternal;
  },
  registerListener: function(listener) {
    this.aListener = listener;
  }
}

Luego puede registrar un oyente utilizando lo siguiente:

x.registerListener(function(val) {
  alert("Someone changed the value of x.a to " + val);
});

Entonces, cada vez que algo cambie el valor de x.a, se activará la función de escucha. Al ejecutar la siguiente línea, aparecerá la ventana emergente de alerta:

x.a = 42;

Vea un ejemplo aquí: https://jsfiddle.net/5o1wf1bn/1/

También puede usar una variedad de oyentes en lugar de una sola ranura de escucha, pero quería darle el ejemplo más simple posible.

Akira
fuente
66
Esta es una tonelada de código por objeto, ¿hay alguna manera de hacer que esto sea más reutilizable?
Vael Victus
¿Dónde está tu código? ¿Comenzaste una nueva pregunta?
Akira
¿Qué pasa con una forma de detectar cuándo se ha agregado una nueva propiedad a un objeto o se ha eliminado una?
Michael
Esta es una respuesta anterior, pero quería agregar que funciona bien para los valores de la matriz, siempre y cuando establezca el valor de la matriz en lugar de presionarla.
TabsNotSpaces
1
Simplemente necesita tener una variedad de oyentes en lugar de uno solo y luego, en lugar de solo llamar this.aListener(val), tendría que recorrer todas las funciones de los oyentes y llamar a cada uno pasar val. Por lo general, se llama al método en addListenerlugar de registerListener.
Akira
75

La mayoría de las respuestas a esta pregunta son obsoletas, ineficaces o requieren la inclusión de grandes bibliotecas hinchadas:

  • Object.watch y Object.observe están en desuso y no deben usarse.
  • onPropertyChange es un controlador de eventos de elementos DOM que solo funciona en algunas versiones de IE.
  • Object.defineProperty le permite hacer que una propiedad de objeto sea inmutable, lo que le permitiría detectar cambios intentados, pero también bloquearía cualquier cambio.
  • Definir setters y getters funciona, pero requiere mucho código de configuración y no funciona bien cuando necesita eliminar o crear nuevas propiedades.

Hoy, ahora puede usar el objeto Proxy para monitorear (e interceptar) los cambios realizados en un objeto. Está diseñado específicamente para lo que el OP está tratando de hacer. Aquí hay un ejemplo básico:

var targetObj = {};
var targetProxy = new Proxy(targetObj, {
  set: function (target, key, value) {
      console.log(`${key} set to ${value}`);
      target[key] = value;
      return true;
  }
});

targetProxy.hello_world = "test"; // console: 'hello_world set to test'

Los únicos inconvenientes del Proxyobjeto son:

  1. El Proxyobjeto no está disponible en navegadores antiguos (como IE11) y el polyfill no puede replicar completamente la Proxyfuncionalidad.
  2. Los objetos proxy no siempre se comportan como se esperaba con objetos especiales (por ejemplo, Date): el Proxyobjeto se combina mejor con objetos o matrices simples.

Si necesita observar los cambios realizados en un objeto anidado , debe usar una biblioteca especializada como Observable Slim (que he publicado) que funciona así:

var test = {testing:{}};
var p = ObservableSlim.create(test, true, function(changes) {
    console.log(JSON.stringify(changes));
});

p.testing.blah = 42; // console:  [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]
Elliot B.
fuente
1
También agregaré otro inconveniente, en realidad no observa los cambios en el objeto de destino, sino solo en el objeto proxy. En algunos casos, solo desea saber cuándo cambia una propiedad en el objeto de destino (es decir target.hello_world = "test")
Cristiano
2
you don't actually watch changes on the target object but only on proxy objectEso no es del todo exacto. El Proxyobjeto no se modifica, no tiene su propia copia del objetivo. you just want to know when a property change on the target object- puede lograr eso con un Proxy, ese es uno de los principales casos de uso para servidores proxy.
Elliot B.
2
No, porque estás modificando el objetivo directamente. Si desea observar la modificación target, debe hacerlo a través de un proxy. Sin embargo proxy.hello_world = "test", no significa que esté modificando el proxy, el proxy permanece sin cambios, targetse modifica (si su controlador de conjunto está configurado para hacerlo). Parece que su punto es que no puede observar directamente target.hello_world = "test". Eso es verdad. Las asignaciones de variables simples no emiten ningún tipo de evento. Es por eso que tenemos que usar herramientas como las descritas en las respuestas a esta pregunta.
Elliot B.
2
Gracias Elliot B. Ese It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.es exactamente mi punto. En mi caso, tengo un objeto creado en otro lugar y actualizado por algún otro código ... un proxy, en este caso, no es útil ya que los cambios se realizarán en el destino.
Cristiano
1
@ Cristiano Creo que lo que Elliot está tratando de decir es que puedes usar el proxy en lugar del objeto real, lo que significa que puedes pasar el proxy como si fuera tu objeto y hacer que las otras partes de la aplicación interactúen con tu proxy. Los cambios en el proxy se reflejarán en el objeto real.
Zoltán Matók
33

No.

Pero, si es realmente tan importante, tiene 2 opciones (la primera se prueba, la segunda no):

Primero, use setters y getters, así:

var myobj = {a : 1};

function create_gets_sets(obj) { // make this a framework/global function
    var proxy = {}
    for ( var i in obj ) {
        if (obj.hasOwnProperty(i)) {
            var k = i;
            proxy["set_"+i] = function (val) { this[k] = val; };
            proxy["get_"+i] = function ()    { return this[k]; };
        }
    }
    for (var i in proxy) {
        if (proxy.hasOwnProperty(i)) {
            obj[i] = proxy[i];
        }
    }
}

create_gets_sets(myobj);

entonces puedes hacer algo como:

function listen_to(obj, prop, handler) {
    var current_setter = obj["set_" + prop];
    var old_val = obj["get_" + prop]();
    obj["set_" + prop] = function(val) { current_setter.apply(obj, [old_val, val]); handler(val));
}

luego configure al oyente como:

listen_to(myobj, "a", function(oldval, newval) {
    alert("old : " + oldval + " new : " + newval);
}

En segundo lugar, en realidad lo olvidé, lo enviaré mientras lo pienso :)

EDITAR: Oh, lo recuerdo :) Podrías vigilar el valor:

Dado myobj arriba, con 'a' en él:

function watch(obj, prop, handler) { // make this a framework/global function
    var currval = obj[prop];
    function callback() {
        if (obj[prop] != currval) {
            var temp = currval;
            currval = obj[prop];
            handler(temp, currval);
        }
    }
    return callback;
}

var myhandler = function (oldval, newval) {
    //do something
};

var intervalH = setInterval(watch(myobj, "a", myhandler), 100);

myobj.set_a(2);
Luke Schafer
fuente
8
"mirar" en realidad no es detectar un cambio. Esto no está basado en eventos, y ciertamente ralentizaría toda la aplicación muy pronto. Estos enfoques en mi humilde opinión nunca deberían ser parte de un proyecto real.
Muhammad bin Yusrat
28

Utilizando Prototype: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

// Console
function print(t) {
  var c = document.getElementById('console');
  c.innerHTML = c.innerHTML + '<br />' + t;
}

// Demo
var myVar = 123;

Object.defineProperty(this, 'varWatch', {
  get: function () { return myVar; },
  set: function (v) {
    myVar = v;
    print('Value changed! New value: ' + v);
  }
});

print(varWatch);
varWatch = 456;
print(varWatch);
<pre id="console">
</pre>

Otro ejemplo

// Console
function print(t) {
  var c = document.getElementById('console');
  c.innerHTML = c.innerHTML + '<br />' + t;
}

// Demo
var varw = (function (context) {
  return function (varName, varValue) {
    var value = varValue;
  
    Object.defineProperty(context, varName, {
      get: function () { return value; },
      set: function (v) {
        value = v;
        print('Value changed! New value: ' + value);
      }
    });
  };
})(window);

varw('varWatch'); // Declare
print(varWatch);
varWatch = 456;
print(varWatch);

print('---');

varw('otherVarWatch', 123); // Declare with initial value
print(otherVarWatch);
otherVarWatch = 789;
print(otherVarWatch);
<pre id="console">
</pre>

Eduardo Cuomo
fuente
El segundo ejemplo es un poco engañoso, varwrequiere 2 argumentos, pero parte de su ejemplo muestra la función que se llama con solo el parámetro de valor.
Hlawuleka MAS
22

Lamento mencionar un tema antiguo, pero aquí hay un pequeño manual para aquellos que (¡como yo!) No ven cómo funciona el ejemplo de Eli Grey:

var test = new Object();
test.watch("elem", function(prop,oldval,newval){
    //Your code
    return newval;
});

Espero que esto pueda ayudar a alguién

javascript es futuro
fuente
99
Watch no es compatible con Chrome o Safari en este momento, solo Firefox
Paul McClean
55
Por red de desarrolladores de mozilla, esto no se recomienda. Object.prototype.watch () fue diseñado solo para pruebas y no debe usarse en el código de producción. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Dennis Bartlett el
44
@PaulMcClean esta respuesta fue en respuesta a la respuesta de Eli Grey que contenía un Polyfill. gist.github.com/eligrey/384583
Aficionado
2
El reloj ha sido desaprobado por Mozilla. Esta respuesta podría ser engañosa.
Arnaud
7

Como la respuesta de Luke Schafer ( nota : esto se refiere a su publicación original; pero todo el punto aquí sigue siendo válido después de la edición ), también sugeriría un par de métodos Get / Set para acceder a su valor.

Sin embargo, sugeriría algunas modificaciones (y es por eso que estoy publicando ...).

Un problema con ese código es que el campo adel objeto myobjes directamente accesible, por lo que es posible acceder a él / cambiar su valor sin activar los oyentes:

var myobj = { a : 5, get_a : function() { return this.a;}, set_a : function(val) { this.a = val; }}
/* add listeners ... */
myobj.a = 10; // no listeners called!

Encapsulamiento

Entonces, para garantizar que los oyentes realmente sean llamados, tendríamos que prohibir ese acceso directo al campo a. ¿Cómo hacerlo? Use un cierre !

var myobj = (function() { // Anonymous function to create scope.

    var a = 5;            // 'a' is local to this function
                          // and cannot be directly accessed from outside
                          // this anonymous function's scope

    return {
        get_a : function() { return a; },   // These functions are closures:
        set_a : function(val) { a = val; }  // they keep reference to
                                            // something ('a') that was on scope
                                            // where they were defined
    };
})();

Ahora puede usar el mismo método para crear y agregar a los oyentes que Luke propuso, ¡pero puede estar seguro de que no hay forma posible de leer o escribir para apasar desapercibido!

Agregar campos encapsulados mediante programación

Todavía en el camino de Luke, propongo ahora una forma simple de agregar campos encapsulados y los respectivos captadores / establecedores a los objetos mediante una simple llamada a la función.

Tenga en cuenta que esto solo funcionará correctamente con los tipos de valor . Para que esto funcione con los tipos de referencia , habría que implementar algún tipo de copia profunda (ver este , por ejemplo).

function addProperty(obj, name, initial) {
    var field = initial;
    obj["get_" + name] = function() { return field; }
    obj["set_" + name] = function(val) { field = val; }
}

Esto funciona igual que antes: creamos una variable local en una función, y luego creamos un cierre.

¿Cómo usarlo? Simple:

var myobj = {};
addProperty(myobj, "total", 0);
window.alert(myobj.get_total() == 0);
myobj.set_total(10);
window.alert(myobj.get_total() == 10);
Bruno Reis
fuente
2
+1 para encapsulación. Ese fue mi primer pensamiento, pero quería la posibilidad de agregar el método create_gets_sets eventualmente, y dado que es indiscriminado, ocultar los valores no es genial :) podemos ir un paso más allá y escribir algunas cosas para ocultar los valores, pero Creo que el código que he publicado es lo suficientemente confuso para la mayoría de la gente ... tal vez si hay llamada a que ...
Lucas Schafer
6

Si usa jQuery {UI} (que todos deberían usar :-)), puede usar .change () con un elemento <input /> oculto.

Chuck Han
fuente
77
No entiendo del todo. ¿Cómo se puede adjuntar una variable a un <input/>elemento oculto ?
Peter Lee
44
Creo que Chuck sugiere que puede establecer el valor de la entrada usando jquery y luego y un detector de eventos .change (). Si actualiza el valor de la entrada con .val (), se activará la devolución de llamada del evento .change ().
jarederaj
2
<input type="hidden" value="" id="thisOne" />y con jQuery $("#thisOne").change(function() { do stuff here });y $("#thisOne").val(myVariableWhichIsNew);luego .change()se disparará.
Khaverim
2
Esta es la mejor solución en mis libros. Simplemente fácil. En lugar de cambiar la variable en su código, por ejemplo var1 = 'new value';, establecerá el valor de esta entrada oculta, luego agregará un oyente para cambiar la variable. $("#val1").on('change', function(){ val1 = this.val(); ... do the stuff that you wanted to do when val1 changed... }); $("#val1").val('new value');
Tom Walker
2
Para cualquiera que tenga el mismo problema que yo, si el evento de cambio no se dispara, intente $ ("# thisOne"). Val (myVariableWhichIsNew) .trigger ('change'). Espero que esto ayude
Alator
6

AngularJS(Sé que esto no es así JQuery, pero eso podría ayudar. [Pure JS es bueno solo en teoría]):

$scope.$watch('data', function(newValue) { ..

donde "datos" es el nombre de su variable en el ámbito.

Hay un enlace a doc.

ses
fuente
Desafortunadamente, te obliga a vincular la variable al alcance
ruX
se dispara solo cuando $scope.$apply()se ejecuta
iamawebgeek
5

Para aquellos que sintonizan un par de años después:

Hay disponible una solución para la mayoría de los navegadores (e IE6 +) que utiliza el evento onpropertychange y la nueva especificación defineProperty. El pequeño inconveniente es que necesitarás hacer de tu variable un objeto dom.

Todos los detalles:

http://johndyer.name/native-browser-get-set-properties-in-javascript/

MandoMando
fuente
3

La funcionalidad que está buscando se puede lograr mediante el uso del método "defineProperty ()", que solo está disponible para los navegadores modernos:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

He escrito una extensión jQuery que tiene una funcionalidad similar si necesita más soporte para varios navegadores:

https://github.com/jarederaj/jQueue

Una pequeña extensión jQuery que maneja devoluciones de llamadas en cola a la existencia de una variable, objeto o clave. Puede asignar cualquier número de devoluciones de llamada a cualquier número de puntos de datos que puedan verse afectados por los procesos que se ejecutan en segundo plano. jQueue escucha y espera a que estos datos que especifiques entren en existencia y luego dispara la devolución de llamada correcta con sus argumentos.

jarederaj
fuente
2

No directamente: necesita un par getter / setter con una interfaz "addListener / removeListener" de algún tipo ... o un complemento NPAPI (pero esa es otra historia).

jldupont
fuente
1
//ex:
/*
var x1 = {currentStatus:undefined};
your need is x1.currentStatus value is change trigger event ?
below the code is use try it.
*/
function statusChange(){
    console.log("x1.currentStatus_value_is_changed"+x1.eventCurrentStatus);
};

var x1 = {
    eventCurrentStatus:undefined,
    get currentStatus(){
        return this.eventCurrentStatus;
    },
    set currentStatus(val){
        this.eventCurrentStatus=val;
      //your function();
    }
};

o

/*  var x1 = {
eventCurrentStatus:undefined,
currentStatus : {
    get : function(){
        return Events.eventCurrentStatus
        },
    set : function(status){
        Events.eventCurrentStatus=status;

    },
}*/
console.log("eventCurrentStatus = "+ x1.eventCurrentStatus);
x1.currentStatus="create"
console.log("eventCurrentStatus = "+ x1.eventCurrentStatus);
x1.currentStatus="edit"
console.log("eventCurrentStatus = "+ x1.eventCurrentStatus);
console.log("currentStatus = "+ x1.currentStatus);

o

/* global variable ku*/
    var jsVarEvents={};
    Object.defineProperty(window, "globalvar1", {//no i18n
        get: function() { return window.jsVarEvents.globalvarTemp},
        set: function(value) { window.window.jsVarEvents.globalvarTemp = value; }
    });
    console.log(globalvar1);
    globalvar1=1;
    console.log(globalvar1);
Avatar
fuente
1

Una solución bastante simple y simplista es usar una llamada de función para establecer el valor de la variable global, y nunca establecer su valor directamente. De esta manera tienes control total:

var globalVar;

function setGlobalVar(value) {
    globalVar = value;
    console.log("Value of globalVar set to: " + globalVar);
    //Whatever else
}

No hay forma de hacer cumplir esto, solo requiere disciplina de programación ... aunque puede usar grep(o algo similar) para verificar que en ninguna parte su código establece directamente el valor deglobalVar .

O podría encapsularlo en un objeto y métodos de captación y configuración de usuarios ... solo un pensamiento.

markvgti
fuente
Para una variable que no es una propiedad de un objeto, se puede acceder, como es el caso con las variables declaradas varen los módulos ES6, esta es la única solución.
amn
1

Por favor, recuerden que la pregunta inicial era para VARIABLES, no para OBJETOS;)

Además de todas las respuestas anteriores, creé una pequeña lib llamada forTheWatch.js , que usa la misma forma para capturar y llamadas a los cambios en las variables globales normales en javascript.

Compatible con las variables JQUERY, no es necesario usar OBJETOS, y puede pasar directamente un ARRAY de varias variables si es necesario.

Si puede ser útil ...: https://bitbucket.org/esabora/forthewatch
Básicamente solo tiene que llamar a la función:
watchIt("theVariableToWatch", "varChangedFunctionCallback");

Y perdón por adelantado si no es relevante.

Soufiane Benrazzouk
fuente
1

La forma más fácil que he encontrado, a partir de esta respuesta :

// variable holding your data
const state = {
  count: null,
  update() {
    console.log(`this gets called and your value is ${this.pageNumber}`);
  },
  get pageNumber() {
    return this.count;
  },
  set pageNumber(pageNumber) {
    this.count = pageNumber;
    // here you call the code you need
    this.update(this.count);
  }
};

Y entonces:

state.pageNumber = 0;
// watch the console

state.pageNumber = 15;
// watch the console
Giorgio Tempesta
fuente
1

En mi caso, estaba tratando de averiguar si alguna biblioteca que estaba incluyendo en mi proyecto estaba redefiniendo mi window.player. Entonces, al comienzo de mi código, acabo de hacer:

Object.defineProperty(window, 'player', {
  get: () => this._player,
  set: v => {
    console.log('window.player has been redefined!');
    this._player = v;
  }
});
José Antonio Postigo
fuente
0

No es directamente posible.

Sin embargo, esto se puede hacer usando CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent

El siguiente método acepta una matriz de nombres de variables como entrada y agrega un detector de eventos para cada variable y activa el evento para cualquier cambio en el valor de las variables.

El método utiliza sondeo para detectar el cambio en el valor. Puede aumentar el valor del tiempo de espera en milisegundos.

function watchVariable(varsToWatch) {
    let timeout = 1000;
    let localCopyForVars = {};
    let pollForChange = function () {
        for (let varToWatch of varsToWatch) {
            if (localCopyForVars[varToWatch] !== window[varToWatch]) {
                let event = new CustomEvent('onVar_' + varToWatch + 'Change', {
                    detail: {
                        name: varToWatch,
                        oldValue: localCopyForVars[varToWatch],
                        newValue: window[varToWatch]
                    }
                });
                document.dispatchEvent(event);
                localCopyForVars[varToWatch] = window[varToWatch];
            }
        }
        setTimeout(pollForChange, timeout);
    };
    let respondToNewValue = function (varData) {
        console.log("The value of the variable " + varData.name + " has been Changed from " + varData.oldValue + " to " + varData.newValue + "!!!"); 
    }
    for (let varToWatch of varsToWatch) {
        localCopyForVars[varToWatch] = window[varToWatch];
        document.addEventListener('onVar_' + varToWatch + 'Change', function (e) {
            respondToNewValue(e.detail);
        });
    }
    setTimeout(pollForChange, timeout);
}

Al llamar al método:

watchVariables(['username', 'userid']);

Detectará los cambios en las variables nombre de usuario y userid.

Ketan Yekale
fuente
0

Con la ayuda de getter y setter , puede definir una clase de JavaScript que haga tal cosa.

Primero, definimos nuestra clase llamada MonitoredVariable:

class MonitoredVariable {
  constructor(initialValue) {
    this._innerValue = initialValue;
    this.beforeSet = (newValue, oldValue) => {};
    this.beforeChange = (newValue, oldValue) => {};
    this.afterChange = (newValue, oldValue) => {};
    this.afterSet = (newValue, oldValue) => {};
  }

  set val(newValue) {
    const oldValue = this._innerValue;
    // newValue, oldValue may be the same
    this.beforeSet(newValue, oldValue);
    if (oldValue !== newValue) {
      this.beforeChange(newValue, oldValue);
      this._innerValue = newValue;
      this.afterChange(newValue, oldValue);
    }
    // newValue, oldValue may be the same
    this.afterSet(newValue, oldValue);
  }

  get val() {
    return this._innerValue;
  }
}

Supongamos que queremos escuchar los moneycambios, creemos una instancia MonitoredVariablecon dinero inicial 0:

const money = new MonitoredVariable(0);

Entonces podríamos obtener o establecer su valor usando money.val:

console.log(money.val); // Get its value
money.val = 2; // Set its value

Como no hemos definido ningún oyente para ello, no sucede nada especial después de los money.valcambios a 2.

Ahora definamos algunos oyentes. Tenemos cuatro oyentes disponibles: beforeSet, beforeChange, afterChange, afterSet. Lo siguiente sucederá secuencialmente cuando use money.val = newValuepara cambiar el valor de la variable:

  1. money.beforeSet (newValue, oldValue);
  2. money.beforeChange (newValue, oldValue); (Se omitirá si su valor no cambia)
  3. money.val = newValue;
  4. money.afterChange (newValue, oldValue); (Se omitirá si su valor no cambia)
  5. money.afterSet (newValue, oldValue);

Ahora definimos el afterChangeoyente que se activará solo después de que money.valhaya cambiado (mientras afterSetque se activará incluso si el nuevo valor es el mismo que el anterior):

money.afterChange = (newValue, oldValue) => {
  console.log(`Money has been changed from ${oldValue} to ${newValue}`);
};

Ahora establezca un nuevo valor 3y vea qué sucede:

money.val = 3;

Verá lo siguiente en la consola:

Money has been changed from 2 to 3

Para obtener el código completo, consulte https://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab .

yusanshi
fuente
-2

Este es un hilo viejo pero me topé con la segunda respuesta más alta (escuchas personalizadas) mientras buscaba una solución usando Angular. Si bien la solución funciona, angular tiene una forma mejor integrada para resolver este uso de @Outputemisores de eventos. Saliendo del ejemplo en la respuesta de escucha personalizada:

ChildComponent.html

<button (click)="increment(1)">Increment</button>

ChildComponent.ts

import {EventEmitter, Output } from '@angular/core';

@Output() myEmitter: EventEmitter<number> = new EventEmitter<number>();

private myValue: number = 0;

public increment(n: number){
  this.myValue += n;

  // Send a change event to the emitter
  this.myEmitter.emit(this.myValue);
}

ParentComponent.html

<child-component (myEmitter)="monitorChanges($event)"></child-component>
<br/>
<label>{{n}}</label>

ParentComponent.ts

public n: number = 0;

public monitorChanges(n: number){
  this.n = n;
  console.log(n);
}

Esto ahora se actualizará nen el padre cada vez que se haga clic en el botón hijo. Pila de trabajo

TabsNotSpaces
fuente
-3
Utils = {
    eventRegister_globalVariable : function(variableName,handlers){
        eventRegister_JsonVariable(this,variableName,handlers);
    },
    eventRegister_jsonVariable : function(jsonObj,variableName,handlers){
        if(jsonObj.eventRegisteredVariable === undefined) {
            jsonObj.eventRegisteredVariable={};//this Object is used for trigger event in javascript variable value changes ku
        }
        Object.defineProperty(jsonObj, variableName , {
                    get: function() { 
                        return jsonObj.eventRegisteredVariable[variableName] },
                    set: function(value) {
                        jsonObj.eventRegisteredVariable[variableName] = value; handlers(jsonObj.eventRegisteredVariable[variableName]);}
                    });
            }
Avatar
fuente