2012-07-26 26 views
6

Al tratar de darle vida a una interfaz de usuario de knockout.js con efectos, he descubierto que a menudo tengo varias secciones que se alternan en función de un condicional. Un ejemplo de esto podría ser un panel de detalles en una vista de lista que muestra instrucciones cuando no se selecciona ningún elemento. Esto funciona de maravilla declarativamente usando el enlace visible, pero se queda corto cuando intentas agregar animaciones a la mezcla, ya que no hay encadenamiento de las animaciones mostrar/ocultar.Encadenamiento declarativo de animaciones knockout.js?

He simplificado la animación knockout.js ejemplo aquí para demostrar:

http://jsfiddle.net/yq5rS/

Mientras que probablemente podría piratear algo, yo estoy buscando una forma más knockout.js idiomática de hacer este tipo de encadenamiento

he considerado algunas soluciones:

  • Tener un elemento contenedor con una unión a medida que captura el elemento condicional y para mostrar en el estados activado y desactivado.
  • Tener el enlace "animación visible" depende tanto del condicional como de una función que comprueba si el otro elemento está oculto.

Editar: Para ser claros, quiero que el fundido de un elemento pase antes que el fundido del otro. Gracias Josh.

+0

No ha especificado que realmente quiere * * suceda. ¿Desea que todos los elementos encuadernados se oculten antes de que se muestren los otros elementos encuadernados? ¿Quieres que entren y salgan al mismo tiempo, pero sin problemas? – Tyrsius

+1

Esto podría ser pura conjetura, pero creo que quiere que las animaciones se ejecuten en serie. Entonces necesitan ser ordenados, uno se esconde, luego el otro muestra, o viceversa. – Josh

+0

De hecho, exactamente Josh. Editar hecho :-) – RasmusKL

Respuesta

3

Este enfoque crea un observables computarizada que se ve a lo observable booleano para determinar el texto a visualizar.

Aquí hay un jsfiddle de trabajo.http://jsfiddle.net/yq5rS/10/

y aquí está una idea rápida del código

HTML

<div class='liveExample'> 
    <p> 
     <label> 
      <input type='checkbox' data-bind='checked: display' /> 
      Active? 
     </label> 
    </p> 

    <p data-bind='fadeVisible: IsActive()'></p>  
</div>​ 

Scripts

var Model = function() { 
    var self = this; 
    self.display= ko.observable(false); 
    self.IsActive = ko.computed(function() { 
     if (self.display()) return "Active." 
     return "Not active." 
    }); 
}; 


ko.bindingHandlers.fadeVisible = { 
    init: function(element, valueAccessor) { 
     var value = valueAccessor(); 
     $(element).hide().html(ko.utils.unwrapObservable(value)).fadeIn(); 
    }, 
    update: function(element, valueAccessor) { 
     var value = valueAccessor(); 
     $(element).hide().html(ko.utils.unwrapObservable(value)).fadeIn(); 
    } 
}; 

ko.applyBindings(new Model());​ 

EDIT

Mi respuesta inicial no se desvanecen, espera, y luego hizo desvanecerse. Aquí es un controlador actualizado vinculante fadeVisible

ko.bindingHandlers.fadeVisible = { 
    update: function(element, valueAccessor) { 
     var value = valueAccessor(); 
     $(element).fadeOut('slow', function() { 
      $(element).html(ko.utils.unwrapObservable(value)).fadeIn(); 
     }); 
    } 
}; 
+1

De hecho, pero esto no elimina el contenido antes de desvanecerse en el nuevo contenido ... – RasmusKL

+0

el problema es con el encadenamiento jquery. $ (Elemento) .fadeOut() no se bloquea por lo que el método .html() se produce durante el fundido percibido. Aquí hay un jsFiddle que resuelve el problema con un http de setTimeout: //jsfiddle.net/yq5rS/12/ –

+0

Así que aquí hay una manera jQuery mucho más segura de "esperar" el fadeOut() http://jsfiddle.net/yq5rS/13/ –

0

Un enfoque que podría funcionar para usted es mostrar dos elementos en el mismo espacio y alternar entre ellos, apegarse a un elemento y usar un enlace personalizado que lo atenúa, intercambia el contenido y luego lo vuelve a fundir Creo que esto funcionaría muy bien para su caso trivial relacionado con jsfiddle.

Eche un vistazo a Ryan Niemeyer's blog y el JSFiddle vinculado. La forma en que se desvanece cambia el total observable calculado parece aplicable a su ejemplo de intercambio de divs.

Sé que probablemente tenga tareas más complicadas que simplemente alternar entre dos divisiones ... pero podría haber una forma de extender la solución a un caso más general. No soy un experto en plantillas, pero ¿has trabajado mucho con ellos? En particular, la sintaxis template { name: function() {} } para dynamically changing templates?

(supongo que esto oficialmente me hace un Fanboy Niemeyer, pero no estoy avergonzado :-P)

+0

De hecho, creé un enlace personalizado que usaba un contenedor y intercambiaba los 2 elementos al desvanecer el contenedor, intercambiando y luego desapareciendo en el contenedor como se ve aquí: http://jsfiddle.net/rasmuskl/QQxXw/ ... Pero luego mi problema se convirtió en otros observables, ya que la IU se actualizaría con los nuevos valores a medida que el contenedor se desvanecía, creando un parpadeo :-(Problema complicado. – RasmusKL