2012-07-11 20 views
5

後說我有一組3個單選按鈕:KnockoutJS:淡入淡出別的

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

當用戶選擇第一個單選按鈕(礦山/自己),則不需要額外的輸入。但是,在選擇第二或第三,額外的輸入時需要

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

,這很容易,只是對相關的文本框data-bind="visible: who() === '[MemberId|MemberUrl]'"。但是,如果我想添加淡入/淡出轉換呢?

我試用了淘汰賽網站上的示例定製fadeVisiblebindingHandler,我理解它是如何工作的。但是,這會在同一時間淡出並在文本框中淡出。如果選擇了無線電'MemberId',而用戶選擇'MemberUrl'收音機,我希望MemberUrl文本框中前衰MemberId文本框淡出

下面是我現在擁有的,它的工作原理,但我不」我認爲它是最優的。除非上一個元素已經淡出,否則還有什麼方法可以讓淘汰賽不執行淡入?我是否需要另一個ko.observale,或者可能需要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); 

回答

9

你必須適應這一點了,以適應你的榜樣,但我需要簡化它在this fiddle測試。

這裏是結合:

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

謝謝Tyrsius的回答。我確實必須從小提琴中適應它。我可以使用稍微修飾的結合讓它具有相同的收音機,在這個問題(沒有一個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

很高興我能幫到你。您可能想要考慮更多面向模型的解決方案。如果您遵循MVVM模式,事情將傾向於更簡單地使用KO。 – Tyrsius 2012-07-11 19:25:33

+0

@Tyrsius,「面向模型的解決方案」,你的意思是使用foreach從vm渲染收音機,而不是在HTML中顯式輸出它們? – danludwig 2012-07-11 19:47:00

+1

是的,除其他外。 MVVM模式中的想法是視圖不包含任何數據,它只知道如何顯示模型。所有的數據應該在模型中。這允許視圖和模型被任何數據使用。 – Tyrsius 2012-07-11 19:53:05

1

有點遲到了,但也許是使用的人其他。

我已經採取Tyrsius的答案,並改變它來解決我自己的需求;這個版本處理一個可觀察的屬性,並且每當它發生變化時將會淡入/淡出舊/新值。

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