2012-07-02 7 views
32

Tengo un problema con el enlace "comprobado" no deseable. Parece que el evento "cambiar" en la casilla de verificación devuelve un valor anterior, antes de que se actualice (por lo que si no se selecciona, devolverá falso). No creo que pueda suscribirme al valor ya que lo tengo dentro del objeto.Evento de cambio de casilla de verificación eliminada envía el valor anterior

<tbody data-bind="foreach: Categories"> 
       <tr> 
        <td><input type="checkbox" data-bind="checked: ShowOpened, event: { change: $root.CategoryChange }" /></td> 
       </tr> 
      </tbody> 
<script type="text/javascript"> 
var Category = function (Id, Name, Order, ShowOpened) { 
    this.Id = Id; 
    this.Name = Name; 
    this.Order = Order; 
    this.ShowOpened = ShowOpened; 
    this.IsUpdated = ko.observable(false); 

    this.OldOrder = Order; 
    this.OldShowOpened = ShowOpened; 
}; 
var ViewModel = { 
    Categories: ko.observableArray([]), 
    CategoryChange: function(pCategory) { 
     if(pCategory.Order != pCategory.OldOrder || pCategory.ShowOpened != pCategory.OldShowOpened) 
      pCategory.IsUpdated(true); 
     else 
      pCategory.IsUpdated(false); 
    } 
}; 
ko.applyBindings(ViewModel); 
</script> 

Así que en este ejemplo he ShowOpened casilla de verificación que puede desencadenar método CategoryChange que va a cambiar una variable dentro del objeto (que necesito más tarde para saber qué objeto se actualiza). Pero cuando se cambia el cuadro de chequeo, siempre envía el valor anterior, el método de activación, y luego cambia el valor. ¿Hay alguna forma de arreglar esto?

+1

Algo está mal con su código. Ni 'ShowOpened' ni' IsUpdated' son ko.observables (y es por eso que siempre obtienes el valor anterior). ¿Cómo puede funcionar este código? 'CategoryChange' debería lanzar una excepción. – freakish

+1

@freakish eres wright, cometí un error al crear esta publicación originalmente. Pero aún así el error que señaló no es el problema. – akhabaiev

+0

Oi, todavía falta esto: 'this.ShowOpened = ko.observable (ShowOpened);' y esto: 'pCategory.ShowOpened()'. Debo decir que cometió muchos errores al escribir esta publicación ... – freakish

Respuesta

57

Ya que persistió en el que indica que la falta de ko.observables no es un problema, he mirado más cerca. ¡Parece que estás en lo correcto! El evento change se dispara antes de se establece el valor real. Me temo que no sé el motivo de esto.

Pero hay una manera fácil de solucionar este problema: basta con cambiar change evento para click evento:

<input type="checkbox" data-bind="checked: ShowOpened, click: $root.CategoryChange" /> 

Recuerde que usted tiene que poner de forma explícita return true; al final de click controlador de eventos. De lo contrario, el nuevo valor no se configurará en la casilla de verificación.

Si no desea utilizar el evento click, puede hacerlo de otra forma. Suscribirse a los cambios de ShowOpened:

this.ShowOpened = ko.observable(ShowOpened); 
this.ShowOpened.subscribe(function(newValue) { 
    /* Do something when ShowOpened changes. 
     newValue variable holds the new value, obviously. :) */ 
}); 
+1

Genial, haga clic en el evento funciona. Lo intenté begore, simplemente me olvidé de devolver verdadero, y la casilla de verificación nunca se marcó/desmarcó. Gracias. – akhabaiev

+0

Tuve exactamente el mismo problema con IE que no reconoce el evento 'change'. Grr. – Brandon

+5

¡Funciona perfecto! Gracias. El "retorno verdadero"; ¡es clave para que esto funcione correctamente! – mikemike396

6

Pruebe usar subscribe en lugar de vincular eventos. Esto debería funcionar ahora

<table> 
    <tbody data-bind="foreach: Categories"> 
     <tr> 
      <td><input type="checkbox" data-bind="checked: ShowOpened" /></td> 
     </tr> 
    </tbody> 
<table> 

var Category = function (Id, Name, Order, ShowOpened) { 
    this.Id = Id; 
    this.Name = Name; 
    this.Order = Order; 
    this.ShowOpened = ko.observable(ShowOpened); 
    this.IsUpdated = false; 

    this.OldOrder = Order; 
    this.OldShowOpened = ShowOpened; 

    this.ShowOpened.subscribe(function (newShowOpened) { 
     if(this.Order != this.OldOrder || this.ShowOpened() != this.OldShowOpened) 
      this.IsUpdated = true; 
     else 
      this.IsUpdated = false; 
    }, this); 
}; 
var ViewModel = { 
    Categories: ko.observableArray([]) 
}; 
ko.applyBindings(ViewModel); 

O como alternativa (y en mi opinión, una solución mejor) que puede utilizar dependentObservable, que ahora se llama computed. Así es como se vería como

<table> 
    <tbody data-bind="foreach: Categories"> 
     <tr> 
      <td> 
       <input type="checkbox" data-bind="checked: ShowOpened" /> 
       <span data-bind="text: IsUpdated"></span> 
      </td> 
     </tr> 
    </tbody> 
</table> 
var Category = function (Id, Name, Order, ShowOpened) { 
    this.Id = Id; 
    this.Name = Name; 
    this.Order = Order; 
    this.ShowOpened = ko.observable(ShowOpened); 
    this.OldOrder = Order; 
    this.OldShowOpened = ShowOpened; 
    this.IsUpdated = ko.computed(function() { 
     return this.Order != this.OldOrder || this.ShowOpened() != this.OldShowOpened; 
    }, this); 
}; 
var ViewModel = { 
    Categories: ko.observableArray([]) 
}; 
ko.applyBindings(ViewModel); 
0

También tuve este problema, pero no pude usar la solución suscribirse porque ya estaba suscrito al mismo campo con una petición Ajax que podría restablecer el valor. El código se mantendría en un bucle cuando lo cambiaras. Así que agregué la siguiente solución (es fea pero funciona).

$("input[type='radio'], input[type='checkbox']", element).on("change", function (e, data) { 
    setTimeout(function() { 
     $(this).trigger("afterChange", data); 
    }.bind(this), 10); 
}); 

Luego, en lugar de escuchar el cambio, escucharía el evento afterChange.

<div data-bind="foreach: answerList"> 
    <input type="checkbox" data-bind="event: { afterChange: $root.sendSelectedAnswer($data) }"/> 
</div> 

Sé que no es la mejor solución, pero en mi caso no tenía otra opción.

Cuestiones relacionadas