2012-07-11 17 views
5

Say Ho una serie di 3 pulsanti:KnockoutJS: dissolvenza dopo dissolvenza qualcos'altro

<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> 

Quando l'utente seleziona il primo pulsante (miniera/Me), non è necessario alcun input aggiuntivo. Tuttavia, quando si seleziona la seconda o terza, ingresso aggiuntivo è richiesto:

<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> 

E 'abbastanza facile avere solo data-bind="visible: who() === '[MemberId|MemberUrl]'" sulle caselle di testo dipendenti. Tuttavia, cosa succede se voglio aggiungere transizioni di dissolvenza in entrata/uscita?

Ho provato l'esempio personalizzato fadeVisiblebindingHandler dal sito a eliminazione diretta, e capisco come funziona. Tuttavia, questo svanirà e scomparirà nelle caselle di testo contemporaneamente. Se si seleziona la radio 'MemberId', e l'utente seleziona 'MemberUrl' radio, voglio che la casella MemberId testo per fade out prima casella MemberUrl di testo svanisce in.

Qui di seguito è quello che ho adesso, e funziona, ma I don' Penso che sia ottimale. In quale altro modo si può dire a knockout di non eseguire la dissolvenza fino a quando un elemento precedente non è stato disattivato? Ho bisogno di un altro ko.observale o forse di 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); 

risposta

9

Si dovrà adattare questo un po 'per misura il vostro esempio, ma avevo bisogno di semplificare per testare in this fiddle.

Ecco il legame:

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

Grazie Tyrsius per la risposta. Dovevo adattarlo dal violino. Sono stato in grado di usare un legame leggermente modificato per farlo funzionare con le stesse radio come nella questione (senza 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

Contento di aver potuto aiutare. Potresti considerare una soluzione più orientata al modello. Le cose tenderanno ad essere più semplici con KO se segui il pattern MVVM. – Tyrsius

+0

@Tyrsius, per "soluzione orientata al modello", si intende l'uso di un foreach per il rendering delle radio dal vm invece di produrle esplicitamente in HTML? – danludwig

+1

Sì, tra le altre cose. L'idea nel pattern MVVM è che la vista non contiene dati, sa solo come visualizzare il tuo modello. Tutti i dati dovrebbero essere nel modello. Ciò consente sia la vista che il modello di essere utilizzati da qualsiasi dato. – Tyrsius

1

Un po 'tardi per il partito, ma forse è utile a qualcuno altro.

Ho preso la risposta di Tyrsius e l'ho cambiata per risolvere i miei bisogni; questa versione si occupa di una proprietà osservabile e dissolvenza/dissolvenza nel valore vecchio/nuovo ogni volta che cambia.

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); 
     } 
    } 
};