way two knockoutjs knockout data change javascript knockout.js durandal

javascript - two - Knockout change event-handler



knockoutjs keyup (1)

Estoy gastando horas tratando de hacer que una simple llamada al evento funcione correctamente en mi aplicación durandal / knockout.

Contexto

Tengo una lista de idiomas que el usuario puede seleccionar de un cuadro de selección:

<select class="form-control select2" data-bind="event: { change: app.languageChanged }, options:languages, optionsText:''label'', optionsValue:''code'', value:app.selectedLanguage"></select>

La propiedad app.selectedLanguage es un ko.observable. Sé que esto funciona porque el elemento correcto es preseleccionado.

this.selectedLanguage = ko.observable(options.defaultLanguage);

También tengo un controlador de eventos que escucha los cambios en esa casilla de selección, para que pueda enviar un mensaje a otras partes de la aplicación que necesitan ser informadas:

languageChanged : function(data, event) { console.log(data); console.log(event); console.log(this.selectedLanguage()); app.trigger(''language:change'', this.selectedLanguage()); },

El problema

  1. el primer parámetro ''datos'' no contiene el elemento seleccionado, sino que contiene todos los elementos (en realidad, parece ser el modelo de vista actual completo).
  2. Si 1. no funciona, entonces sería una alternativa para al menos obtener el nuevo valor del ''idioma seleccionado'' observable. Desafortunadamente, eso siempre parece tener el valor anterior. Entonces cada vez que cambio la opción de selección de cuadro de selección, siempre obtengo el valor previamente seleccionado.

Pregunta

Entonces la pregunta es: ¿qué podría estar haciendo mal? Estoy seguro de que esto normalmente funciona correctamente y me falta algo en alguna parte.

Pensé que finalmente había entendido cómo funciona el knockout, pero ahora me he topado con el siguiente número. Estaría muy agradecido si alguien pudiera ayudarme en esto.

EDITAR [SOLUCIONADO]

Gracias a xdumaine, aquí está la solución (agradable y simple):

En mi plantilla html, eliminé el evento de cambio:

<select class="form-control select2" data-bind="options:languages, optionsText:''label'', optionsValue:''code'', value:app.selectedLanguage"></select>

En mi modelo de vista de aplicación (que necesito en todas partes), ahora me suscribo al ko.observable en lugar de escuchar el controlador de eventos:

define([ ''durandal/app'', ''underscore'', ''knockout'', ''myapp/myapp'' ], function(app, _, ko, myapp) { "use strict"; function App(options) { if (!(this instanceof App)) { throw new TypeError("App constructor cannot be called as a function."); } this.options = options || {}; // Set the initial language. this.selectedLanguage = ko.observable(options.defaultLanguage); // *** Subscribes to the observable *** this.selectedLanguage.subscribe(function(newValue) { console.log(newValue); app.trigger(''language:change'', newValue); }); _.bindAll(this, ''getSelectedLanguage''); } App.prototype = { constructor : App, getSelectedLanguage : function() { return this.selectedLanguage(); } } return App; });

Por lo tanto, este código se ha eliminado y ya no es necesario:

languageChanged : function(data, event) { console.log(data); console.log(event); console.log(this.selectedLanguage()); app.trigger(''language:change'', this.selectedLanguage()); },

Saludos, Michael


¿Por qué vincularse al evento de cambio de selección en lugar de solo suscribirse a la lengua seleccionada?

var self = this; self.selectedLanguage = ko.observable(); self.selectedLangauge.subscribe(function(newValue) { console.log(newValue); app.trigger(''language:change'', newValue); });

Si quieres hacerlo como lo tienes, debes saber esto: las asociaciones de eventos en knockout siempre obtienen una referencia al viewModel como el primer parámetro, y los datos del evento como el segundo, por lo que podrías tener que inspeccionar el evento para obtener el objetivo y extraer el valor si lo haces de esa manera. La razón por la que 2 no funciona es porque tu evento de cambio se activa antes de que se notifique la observación observable, por lo que obtienes problemas de sincronización. Esto podría tener un comportamiento diferente en diferentes navegadores.

Recomiendo adherirse a suscripciones observables, en lugar de usar eventos DOM, siempre que sea posible.