Jak szablonować struktury If-Else w widokach powiązanych z danymi?

95

Ciągle używam tego idiomu w szablonach HTML opartych na KO:

<!-- ko if: isEdit -->
<td><input type="text" name="email" data-bind="value: email" /></td>
<!-- /ko -->
<!-- ko ifnot: isEdit -->
<td data-bind="text: email"></td>
<!-- /ko -->

Czy istnieje lepszy / czystszy sposób wykonywania warunków warunkowych w KO, czy też istnieje lepsze podejście niż zwykłe używanie tradycyjnych konstrukcji if-else?

Chciałbym również zaznaczyć, że niektóre wersje przeglądarki Internet Explorer (IE 8/9) nie analizują poprawnie powyższego przykładu. Aby uzyskać więcej informacji, zobacz to pytanie SO . Krótkie podsumowanie brzmi: nie używaj komentarzy (wirtualnych powiązań) wewnątrz tagów tabeli do obsługi IE. Użyj tbodyzamiast tego:

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>
Jensen Ching
źródło
Każdy, kto na to spojrzy,
Brian M. Hunt

Odpowiedzi:

64

Istnieje kilka różnych sposobów obsługi tego typu kodu.

  • z kombinacją if / ifnot, tak jak teraz. To działa dobrze i nie jest strasznie rozwlekłe.

  • Wiązanie przełącznika / wielkości liter Michaela Besta ( https://github.com/mbest/knockout-switch-case ) jest dość elastyczne i pozwala łatwo obsłużyć to i bardziej skomplikowane (więcej stanów niż prawda / fałsz).

  • Inną opcją jest użycie szablonów dynamicznych. Powiążesz obszar z jednym lub wieloma szablonami, używając nazwy szablonu opartej na obserwowalnym. Oto post, który napisałem na ten temat jakiś czas temu: http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html . W Twoim scenariuszu może to wyglądać tak:

<td data-bind="template: $root.getCellTemplate"></td>

<script id="cellEditTmpl" type="text/html">
    <input type="text" name="email" data-bind="value: email" />
</script>

<script id="cellTmpl" type="text/html">
    <span data-bind="text: email"></span>
</script>

getCellTemplateFunkcja może żyć wszędzie, ale byłby określony element ($ dane) jako pierwszy argument i zwróci nazwę szablonu do użytku.

RP Niemeyer
źródło
dziwne, mój kod HTML się nie wyświetla. Właśnie zauważyłem, że Michael udzielił prawie takiej samej odpowiedzi.
RP Niemeyer,
Dzięki za wyczerpującą listę opcji. Myślę, że mój oryginalny styl kodu działa w prostych przypadkach. W razie potrzeby sprawdzę inne opcje.
Jensen Ching,
czy istnieje sposób na jeszcze większe dostosowanie szablonu, na przykład „template: data, proppertyName: 'email'” oraz w szablonie data-bind = "text: $ data [propertyName]".
Onur Topal
@OnurTOPAL - tak, o ile masz zmienną propertyName, możesz dynamicznie określić nazwę szablonu.
RP Niemeyer
44

Jedną z metod jest użycie nazwanych szablonów (które mogą obsługiwać przekazywanie argumentów):

<!-- ko template: isEdit() ? 'emailEdit' : 'emailDisplay' --><!-- /ko -->
<script id="emailEdit" type="text/html">
    <td><input type="text" name="email" data-bind="value: email" /></td>
</script>
<script id="emailDisplay" type="text/html">
    <td data-bind="text: email"></td>
</script>

Inną opcją jest użycie mojej wtyczki switch / case , która działałaby tak:

<!-- ko switch -->
    <!-- ko case: isEdit -->
        <td><input type="text" name="email" data-bind="value: email" /></td>
    <!-- /ko -->
    <!-- ko case: $else -->
        <td data-bind="text: email"></td>
    <!-- /ko -->
<!-- /ko -->
Michael Best
źródło
Dzięki. Będę pamiętać o wtyczce przełącznika / obudowy, gdy zajdzie taka potrzeba.
Jensen Ching,
2
Dobra wtyczka, którą masz! Na pewno skorzystam z tego.
Kukks
Nazwane szablony działają świetnie i obsługują scenariusze typu if elseif elseif else przez zagnieżdżanie operatora terniary.
4

Aby uniknąć ponownego obliczania wiązania typu knockout przy użyciu kombinacji if: / ifnot: możesz ich używać w połączeniu z konstrukcją „with:”

    <!-- ko with: $data.DoSomePerformanceCriticalWork($data.SomeParameter()) -->
        <!-- ko if: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
        <!-- ko ifnot: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
    <!-- /ko -->
Dmitry Komin
źródło
1

Jest teraz również knockout-elsepowiązanie / wtyczka (którą napisałem, aby rozwiązać ten problem).

Brian M. Hunt
źródło