2012-07-11 5 views
5

Ausblendung sagen, dass ich einen Satz von 3 Radiobuttons habe:KnockoutJS: verblassen in nach etwas anderen

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

Wenn der Benutzer das erste Optionsfeld (Bergwerk/Myself), keine zusätzliche Eingabe erforderlich ist. Wenn jedoch die zweite oder dritte, zusätzliche Eingangs Auswahl ist erforderlich:

<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 ist leicht genug, nur data-bind="visible: who() === '[MemberId|MemberUrl]'" auf den abhängigen Textfelder haben. Was aber, wenn ich Fade-In/Out-Übergänge hinzufügen möchte?

Ich habe das Beispiel benutzerdefinierte fadeVisiblebindingHandler aus der KO-Site ausprobiert, und ich verstehe, wie es funktioniert. Dies wird jedoch in den Textfeldern gleichzeitig ausgeblendet und ausgeblendet. Wenn Radio 'MemberId' ausgewählt ist, und Benutzer wählt 'MemberUrl' Radio, mag ich das MemberId Textfeld auszublenden vor das MemberUrl Textfeld eingeblendet wird.

Im Folgenden finden Sie, was ich habe jetzt, und es funktioniert, aber ich don‘ Ich denke, es ist optimal. Wie sonst kann Knockout gesagt werden, das Einblenden nicht durchzuführen, bis ein vorheriges Element ausgeblendet wurde? Brauche ich noch eine ko.observale oder möglicherweise eine 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); 

Antwort

9

Sie haben diese ein wenig anpassen Ihr Beispiel passen, aber ich brauchte es zur Vereinfachung in this fiddle zu testen.

Hier ist die Bindung:

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

Danke Tyrsius für die Antwort. Ich musste es von der Geige anpassen. Ich konnte eine leicht modifizierte Bindung verwenden, um es mit den gleichen Radios wie in der Frage (ohne foreach) zu arbeiten:

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

Ich bin froh, dass ich helfen konnte. Vielleicht möchten Sie eine modellorientierte Lösung in Erwägung ziehen. Mit KO werden die Dinge einfacher, wenn Sie dem MVVM-Muster folgen. – Tyrsius

+0

@Tyrsius, von "modellorientierte Lösung", meinst du eine foreach zu verwenden, um die Radios von der VM zu rendern, anstatt sie explizit in HTML auszugeben? – danludwig

+1

Ja, unter anderem. Die Idee im MVVM-Muster ist, dass die Ansicht keine Daten enthält, sondern nur, wie Sie Ihr Modell anzeigen können. Alle Daten sollten im Modell sein. Dadurch können sowohl die Ansicht als auch das Modell von beliebigen Daten verwendet werden. – Tyrsius

1

Ein bisschen spät, um die Partei, aber vielleicht ist es von Nutzen jemand sonst.

Ich habe Tyrsius 'Antwort genommen und geändert, um meine eigenen Bedürfnisse zu beheben; Diese Version behandelt eine beobachtbare Eigenschaft und fadeOut/fadeIn den alten/neuen Wert, wann immer sich dieser ändert.

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