Bagaimana cara membuat template struktur If-Else dalam tampilan terikat data?

95

Saya terus-menerus menemukan diri saya menggunakan idiom ini dalam template HTML berbasis 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 -->

Apakah ada cara yang lebih baik / lebih bersih untuk melakukan kondisional dalam KO, atau adakah pendekatan yang lebih baik daripada hanya menggunakan konstruksi if-else tradisional?

Selain itu, saya hanya ingin menunjukkan bahwa beberapa versi Internet Explorer (IE 8/9) tidak mengurai contoh di atas dengan benar. Silakan lihat pertanyaan SO ini untuk informasi lebih lanjut. Ringkasan singkatnya adalah, jangan gunakan komentar (pengikatan virtual) di dalam tag tabel untuk mendukung IE. Gunakan sebagai tbodygantinya:

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>
Jensen Ching
sumber
Siapa pun yang melihat ini mungkin ingin melacak github.com/knockout/knockout/issues/962
Brian M. Hunt

Jawaban:

64

Ada beberapa cara berbeda untuk menangani jenis kode ini.

  • dengan kombinasi if / ifnot seperti Anda sekarang. Ini bekerja dengan baik dan tidak terlalu bertele-tele.

  • Switch / case binding Michael Best ( https://github.com/mbest/knockout-switch-case ) cukup fleksibel dan memungkinkan Anda menangani hal ini dengan mudah dan yang lebih rumit (lebih banyak status daripada true / false).

  • Pilihan lainnya adalah menggunakan template dinamis. Anda akan mengikat suatu area ke satu atau lebih templat dengan nama templat yang digunakan berdasarkan observasi. Berikut adalah posting yang saya tulis tentang topik ini beberapa waktu lalu: http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html . Dalam skenario Anda, mungkin terlihat seperti:

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

The getCellTemplateFungsi bisa hidup di mana pun, tapi akan diberikan item ($ data) sebagai argumen pertama dan akan kembali nama template untuk digunakan.

RP Niemeyer
sumber
aneh, HTML saya tidak akan muncul. Juga memperhatikan bahwa Michael memberikan jawaban yang kurang lebih sama.
RP Niemeyer
Terima kasih untuk daftar pilihan yang lengkap. Saya kira gaya kode asli saya berfungsi untuk kasus sederhana. Saya akan memeriksa opsi lain saat diperlukan.
Jensen Ching
apakah ada cara untuk menyesuaikan template lebih lanjut, seperti "template: data, proppertyName: 'email'" dan di template data-bind = "text: $ data [propertyName]".
Onur Topal
@OnurTOPAL - ya selama Anda memiliki variabel propertyName, Anda dapat menentukan nama template secara dinamis.
RP Niemeyer
44

Salah satu pendekatannya adalah dengan menggunakan template bernama (yang dapat mendukung penerusan argumen):

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

Opsi lainnya adalah menggunakan plugin switch / case saya , yang akan berfungsi seperti ini:

<!-- 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
sumber
Terima kasih. Saya akan mengingat plugin sakelar / casing saat dibutuhkan.
Jensen Ching
2
Plugin bagus yang Anda dapatkan di sana! Akan menggunakan yang ini pasti.
Kukks
Template bernama berfungsi dengan baik, dan mendukung skenario tipe if elseif elseif else dengan menumpuk operator terniary.
4

Untuk menghindari penghitungan ulang pengikatan sistem gugur saat menggunakan kombinasi if: / ifnot: Anda dapat menggunakannya dalam hubungannya dengan konstruksi 'with:'

    <!-- ko with: $data.DoSomePerformanceCriticalWork($data.SomeParameter()) -->
        <!-- ko if: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
        <!-- ko ifnot: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
    <!-- /ko -->
Dmitry Komin
sumber
1

Sekarang ada juga knockout-elsepengikat / plugin (yang saya tulis untuk mengatasi masalah ini).

Brian M. Hunt
sumber