2012-07-11 25 views
5

Decir que tengo un juego de 3 botones de radio:KnockoutJS: Fundido de entrada después de desvanecimiento algo más

<div> 
    <label> 
     <input type="radio" name="Who" value="Myself" 
      checked="@isMyselfChecked" data-bind="checked: who" /> 
     Mine 
    </label> 
    <label> 
     <input type="radio" name="Who" value="MemberId" 
      checked="@isMemberIdChecked" data-bind="checked: who" /> 
     I know the member's ID 
    </label> 
    <label> 
     <input type="radio" name="Who" value="MemberUrl" 
      checked="@isMemberUrlChecked" data-bind="checked: who" /> 
     I know the member's URL 
    </label> 
</div> 

Cuando el usuario selecciona el primer botón (Mine/yo), no se requiere ninguna entrada adicional. Sin embargo, al seleccionar la segunda o tercera, de entrada adicional de es necesario:

<div> 
    <input type="text" name="MemberId" placeholder="Enter Member ID" 
     data-bind="toggleWho: who()" style="display: none" /> 
    <input type="text" name="MemberUrl" placeholder="Enter Member URL" 
     data-bind="toggleWho: who()" style="display: none; width: 450px;" /> 
</div> 

Es bastante fácil tener sólo data-bind="visible: who() === '[MemberId|MemberUrl]'" en los cuadros de texto dependientes. Sin embargo, ¿qué sucede si quiero agregar transiciones de fundido de entrada/salida?

Probé el ejemplo personalizado fadeVisiblebindingHandler del sitio de eliminación directa, y entiendo cómo funciona. Sin embargo, esto se desvanecerá y se desvanecerá en los cuadros de texto al mismo tiempo. Si se selecciona la radio 'MemberId', y el usuario selecciona 'MemberUrl' de radio, quiero que el cuadro de MemberId texto alcanza el volumen mínimo antes la caja MemberUrl texto se desvanece en.

A continuación se muestra lo que tengo ahora, y funciona, pero yo no' Creo que es óptimo. ¿De qué otra manera se le puede decir a un novato que no realice el fundido de entrada hasta que se haya desvanecido un elemento anterior? ¿Necesito otro ko.observale, o posiblemente un ko.computed?

var viewModel = { 
    fadeSpeed: 150, 
    who: ko.observable($('input[type=radio][name=Who]:checked').val()) 
}; 

ko.bindingHandlers.toggleWho = { 
    init: function (element, valueAccessor) { 
     var value = valueAccessor(); 
     var unwrapped = ko.utils.unwrapObservable(value); 
     if (unwrapped === element.name) 
      $(element).show(); 
    }, 
    update: function (element, valueAccessor) { 
     var value = valueAccessor(); 
     var unwrapped = ko.utils.unwrapObservable(value); 

     // when selected value is myself, fade out the visible one, if any 
     if (unwrapped === 'Myself') { 
      $('input[type=text][name=MemberId]:visible') 
       .fadeOut(viewModel.fadeSpeed); 
      $('input[type=text][name=MemberUrl]:visible') 
       .fadeOut(viewModel.fadeSpeed); 
     } 

      // when selected value is memberid, may need to fade out url first 
     else if (unwrapped === 'MemberId') { 
      if ($('input[type=text][name=MemberUrl]:visible').length > 0) { 
       $('input[type=text][name=MemberUrl]:visible') 
        .fadeOut(viewModel.fadeSpeed, function() { 
         $('input[type=text][name=MemberId]') 
          .fadeIn(viewModel.fadeSpeed); 
        }); 
      } else { 
       $('input[type=text][name=MemberId]') 
        .fadeIn(viewModel.fadeSpeed); 
      } 
     } 

      // when selected value is memberurl, may need to fade out id first 
     else if (unwrapped === 'MemberUrl') { 
      if ($('input[type=text][name=MemberId]:visible').length > 0) { 
       $('input[type=text][name=MemberId]:visible') 
        .fadeOut(viewModel.fadeSpeed, function() { 
         $('input[type=text][name=MemberUrl]') 
          .fadeIn(viewModel.fadeSpeed); 
       }); 
      } else { 
       $('input[type=text][name=MemberUrl]') 
        .fadeIn(viewModel.fadeSpeed); 
      } 
     } 
    } 
}; 

ko.applyBindings(viewModel); 

Respuesta

9

Usted tendrá que adaptar esta un poco para adaptarse a su ejemplo, pero necesitaba para simplificarlo para probar en this fiddle.

Aquí está el enlace:

var previousElement = null; 
ko.bindingHandlers.fadeSwitcher = { 
    init: function(element, valueAccessor) { 
     var value = valueAccessor(); 
     $(element).toggle(ko.utils.unwrapObservable(value)); 
    }, 
    update: function(element, valueAccessor) { 

     var value = ko.utils.unwrapObservable(valueAccessor()); 
     if (value) { 
      if (previousElement == null) { // initial fade 
       $(element).fadeIn(); 
      } else { 
       $(previousElement).fadeOut('fast', function() { 
        $(element).fadeIn(); 
       }); 
      } 
      previousElement = element; 
     }   
    } 
}; 
0

Gracias Tyrsius por la respuesta. Tuve que adaptarlo del violín. Yo era capaz de utilizar una unión ligeramente modificado para conseguir que funcione con los mismos radios como en la pregunta (sin foreach):

@* radios same as in question *@ 
<div> 
    <input type="text" name="MemberId" placeholder="Enter Member ID" 
     data-bind="whoFader: who() === 'MemberId'" style="display: none" /> 
    <input type="text" name="MemberUrl" placeholder="Enter Member URL" 
     data-bind="whoFader: who() === 'MemberUrl'" 
     style="display: none; width: 450px;" /> 
</div> 

ko.bindingHandlers.whoFader = { 
    previousElement: null, 
    init: function (element, valueAccessor) { 
     var value = valueAccessor(); 
     $(element).toggle(ko.utils.unwrapObservable(value)); 
    }, 
    update: function (element, valueAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     if (value) { 
      if (this.previousElement == null) { 
       $(element).fadeIn('fast'); 
      } else { 
       $(this.previousElement).hide(); 
       $(element).fadeIn('fast'); 
      } 
      this.previousElement = element; 
     } 
     else { 
      $(element).fadeOut('fast'); 
     } 
    } 
}; 
+0

Glad I could help. Es posible que desee considerar una solución más orientada a modelos. Las cosas tenderán a ser más simples con KO si sigues el patrón de MVVM. – Tyrsius

+0

@Tyrsius, por "solución orientada a modelos", ¿quiere decir usar un foreach para procesar las radios desde la vm en lugar de emitirlas explícitamente en HTML? – danludwig

+1

Sí, entre otras cosas. La idea en el patrón MVVM es que la vista no contiene ningún dato, solo sabe cómo mostrar su modelo. Todos los datos deben estar en el modelo. Esto permite que tanto la vista como el modelo sean utilizados por cualquier dato. – Tyrsius

1

Un poco tarde a la fiesta, pero tal vez es de utilidad para alguien más.

He tomado la respuesta de Tyrsius y la he cambiado para solucionar mis propias necesidades; esta versión trata de una propiedad observable y desvanecerá/desvanecerá el valor anterior/nuevo cada vez que cambie.

Usage example: <span data-bind="fadeSwitcher: myObservable"></span> 

ko.bindingHandlers.fadeSwitcher = { 
    init: function (element, valueAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     element.setAttribute('previousValue', value); 
     ko.bindingHandlers.text.update(element, ko.observable(value)); 
    }, 
    update: function (element, valueAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     var previousValue = element.getAttribute('previousValue'); 
     if (value !== previousValue) { 
      $(element).fadeOut('fast', function() { 
       ko.bindingHandlers.text.update(element, ko.observable(value)); 
       $(element).fadeIn(); 
      }); 
      element.setAttribute('previousValue', value); 
     } 
    } 
}; 
Cuestiones relacionadas