Bisakah Anda menelepon ko.applyBindings untuk mengikat sebagian tampilan?

258

Saya menggunakan KnockoutJS dan memiliki tampilan utama dan model tampilan. Saya ingin dialog (UI jQuery satu) muncul dengan tampilan lain yang terikat model tampilan anak terpisah.

HTML untuk konten dialog diambil menggunakan AJAX jadi saya ingin dapat menelepon ko.applyBindingssetelah permintaan selesai, dan saya ingin mengikat model tampilan anak untuk hanya bagian dari HTML yang dimuat melalui ajax di dalam dialog dialog.

Apakah ini benar-benar mungkin atau apakah saya perlu memuat SEMUA pandangan saya dan melihat model ketika halaman awalnya dimuat dan kemudian menelepon ko.applyBindingssekali?

Charlie
sumber

Jawaban:

431

ko.applyBindings menerima parameter kedua yang merupakan elemen DOM untuk digunakan sebagai root.

Ini akan memungkinkan Anda melakukan sesuatu seperti:

<div id="one">
  <input data-bind="value: name" />
</div>

<div id="two">
  <input data-bind="value: name" />
</div>

<script type="text/javascript">
  var viewModelA = {
     name: ko.observable("Bob")
  };

  var viewModelB = {
     name: ko.observable("Ted")
  };

  ko.applyBindings(viewModelA, document.getElementById("one"));
  ko.applyBindings(viewModelB, document.getElementById("two"));
</script>

Jadi, Anda bisa menggunakan teknik ini untuk mengikat viewModel ke konten dinamis yang Anda muat ke dialog Anda. Secara keseluruhan, Anda hanya ingin berhati-hati untuk tidak menelepon applyBindingsberkali-kali pada elemen yang sama, karena Anda akan membuat beberapa penangan acara terpasang.

RP Niemeyer
sumber
17
Jika Anda juga ingin menghapus binding di beberapa titik di ujung jalan Anda dapat memanggil baik ko.cleanNode(document.getElementById("one")untuk membersihkan barang-barang atau ko.removeNode(document.getElementById("one")untuk membersihkan barang-barang dan menghapus simpul dari DOM.
Michael Berkompas
7
Catat saja itu cleanNodedan removeNodetidak akan menghapus event handler, jadi berhati-hatilah. Dalam beberapa kasus, lebih baik menggunakan templateatau withmengikat area tersebut, sehingga Anda memiliki elemen baru yang diberikan.
RP Niemeyer
7
Saat ini ada sesuatu yang kurang dalam KO. Kami tidak secara khusus bermaksud agar orang-orang "memberontak" bagian. Namun, KO memang melampirkan acara menggunakan jQuery, jika direferensikan, sehingga Anda dapat $(element).unbind();menghapus semua penangan.
RP Niemeyer
5
Di mana fungsi-fungsi ini (applyBindings, cleanNode, removeNode) didokumentasikan? Saya tidak dapat menemukan tanda tangan fungsinya di knockoutjs.com.
EricP
2
Akan lebih baik jika ini adalah suatu tempat yang mudah ditemukan di dalam dokumentasi. Aku bahkan tidak melihat menyebutkannya.
Travis Kaufman
61

Sementara jawaban Niemeyer adalah jawaban yang lebih benar untuk pertanyaan, Anda juga bisa melakukan hal berikut:

<div>
  <input data-bind="value: VMA.name" />
</div>

<div>
  <input data-bind="value: VMB.name" />
</div>

<script type="text/javascript">
  var viewModels = {
     VMA: {name: ko.observable("Bob")},
     VMB: {name: ko.observable("Ted")}
  };

  ko.applyBindings(viewModels);
</script>

Ini berarti Anda tidak perlu menentukan elemen DOM, dan Anda bahkan dapat mengikat banyak model ke elemen yang sama, seperti ini:

<div>
  <input data-bind="value: VMA.name() + ' and ' + VMB.name()" />
</div>
mhu
sumber
4
Anda juga dapat menggunakan "with" untuk mengalokasikan wilayah halaman ke masing-masing model - data-bind = "dengan: VMA"
lexicalscope
3
@flamingpenguin: Ya, tapi withtidak murah, lihat: tautan
mhu
7

Saya telah berhasil mengikat model khusus ke suatu elemen saat runtime. Kode di sini: http://jsfiddle.net/ZiglioNZ/tzD4T/457/

Yang menarik adalah saya menerapkan atribut data-bind ke elemen yang tidak saya definisikan:

    var handle = slider.slider().find(".ui-slider-handle").first();
    $(handle).attr("data-bind", "tooltip: viewModel.value");
    ko.applyBindings(viewModel.value, $(handle)[0]);
ZiglioUK
sumber
mengalami masalah dengan ko 2.3, kode di atas adalah dalam handler pelanggan yang dipanggil ketika saya menerapkan global ko.applyBindings (). Jadi sekarang saya mendapatkan kesalahan "Anda tidak dapat menerapkan binding beberapa kali ke elemen yang sama." Saya masih mencoba mencari tahu mengapa saya mendapatkan kesalahan. Tidak bisakah kita menerapkan pengikatan ke variabel yang sama beberapa kali, masing-masing ke elemen yang berbeda?
ZiglioUK
Inilah versi dengan ko 2.3 yang tidak berfungsi: jsfiddle.net/ZiglioNZ/tzD4T/458
ZiglioUK
Menambahkan panggilan ke ko.cleanNode () sebelum memanggil applyBinding ke tampilan sebagian sepertinya tidak membantu: jsfiddle.net/ZiglioNZ/tzD4T/459
ZiglioUK
Diselesaikan: Saya bahkan tidak perlu menelepon applyBindings!
ZiglioUK
ive baru saja mengedit kode sumber knockoutjs dan berkomentar bagian di mana fungsi twrows "Anda tidak dapat menerapkan binding beberapa kali ke elemen yang sama.", sekarang semua berfungsi ok ... saya tahu ini adalah solusi kotor tetapi saya baru di perpustakaan jadi saya tidak tahu bagaimana untuk tidak menerapkannya beberapa kali untuk masalah saya.
Geomorillo