2012-07-11 16 views
5

Say mam zestaw 3 przyciski radia:KnockoutJS: Obraz pojawia się po zanikaniem coś innego

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

Gdy użytkownik wybierze pierwszą opcję (kopalnia/ja), nie jest wymagane dodatkowe wejście. Jednak przy wyborze drugiego lub trzeciego, dodatkowego wejścia jest wymagane:

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

Łatwo jest po prostu mieć data-bind="visible: who() === '[MemberId|MemberUrl]'" na utrzymaniu polach tekstowych. Co jednak, jeśli chcę dodać przejścia między wejściami i wyjściami?

Wypróbowałem przykład niestandardowy fadeVisiblebindingHandler z witryny nokautowej i rozumiem, jak to działa. To jednak zniknie i znikną w polach tekstowych w tym samym czasie. Jeśli radiowy 'MemberId' jest zaznaczone, a użytkownik wybiera 'MemberUrl' radia, chcę okno MemberId tekst do zanikania przed pole MemberUrl tekst zanika w.

Poniżej jest to, co mam teraz, i to działa, ale don” Uważam, że jest optymalna. Jak inaczej może zostać nokautowany, aby nie przeprowadzać zanikania, dopóki poprzedni element nie zniknie? Czy potrzebuję kolejnego ko.observale lub ewentualnie 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); 

Odpowiedz

9

Będziesz musiał dostosować to trochę dopasować swój przykład, ale potrzebny do uproszczenia go przetestować w this fiddle.

Oto oprawa:

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

Dziękuję Tyrsius na odpowiedź. Musiałem to zaadaptować z skrzypiec. I był w stanie wykorzystać nieco zmodyfikowane wiązania się zmusić go do pracy z tymi samymi radia jak w pytaniu (bez 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

Cieszę się, że mogę pomóc. Możesz rozważyć bardziej zorientowane na model rozwiązanie. Sprawy będą prostsze z KO, jeśli zastosujesz wzór MVVM. – Tyrsius

+0

@Tyrsius, przez "rozwiązanie zorientowane na model", czy używasz foreach do renderowania radia z vm, zamiast wyprowadzać je jawnie w HTML? – danludwig

+1

Tak, między innymi. Idea wzorca MVVM polega na tym, że widok nie zawiera żadnych danych, a jedynie wie, jak wyświetlić model. Wszystkie dane powinny znajdować się w modelu. Dzięki temu zarówno widok, jak i model mogą być używane przez dowolne dane. – Tyrsius

1

Trochę późno do partii, ale być może jest to przydatne dla kogoś jeszcze.

Wziąłem odpowiedź Tyrsiusa i zmieniłem ją, aby naprawić moje własne potrzeby; ta wersja zajmuje się obserwowalną właściwością i będzie fadeOut/fadeIn starej/nowej wartości, gdy tylko się zmieni.

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); 
     } 
    } 
}; 
Powiązane problemy