Bootstrap-multiselect: KnockoutJS mengikat nilai objek (bukan nilai sederhana) ... Perbaikan peretasan termasuk

Dibuat pada 2 Mei 2015  ·  3Komentar  ·  Sumber: davidstutz/bootstrap-multiselect

Saya menggunakan pengikatan pilihan knockout di mana seluruh objek terikat sebagai nilai ... bukan hanya string.

bootstrap-multiselect tidak menyukai ini karena menggunakan "nilai" untuk menghubungkan item daftar dropdown kembali ke opsi pilih yang sesuai. Untuk melakukan ini, Anda harus menyetel atribut "optionsValue" di penjilidan KO Anda sehingga opsi memiliki atribut "nilai". Namun, menyetel atribut "optionsValue" kemudian memiliki hasil yang diharapkan dari hanya menyetel nilai itu di selectedOptions observableArray saya ... bukan seluruh objek.

Sangat mungkin bahwa saya satu-satunya orang yang menggunakan fungsionalitas dalam knockout yang memungkinkan Anda mengikat opsi ke seluruh objek, tetapi untuk berjaga-jaga jika saya tidak ... inilah perbaikan peretasan:

Membuat dua opsi bootstrap-multiselect baru yang disebut "optionsKey" dan "observableKey" sehingga ia tahu ke mana harus mencari nilai yang dapat dikaitkan dengannya:

<select id="mySelect" data-bind="options: myOptions, selectedOptions: mySelectedOptions, optionsText: 'myDisplayText', optionsAfterRender: SetOptionKey, multiselect: { optionsKey: 'data-key', observableKey: 'Key' }" multiple="multiple"></select>

Dalam model tampilan knockout saya, saya mengatur atribut yang direferensikan oleh "optionsKey" pada setiap opsi:

myVM.SetOptionKey = function ( option, item ) {
    ko.applyBindingsToNode( option, { attr: { "data-key": item.Key } }, item );
};

Sekarang saya masuk ke file bootstrap-multiselect.js. Hal pertama yang harus saya lakukan di sini adalah di bagian atas di mana ia menambahkan handler init knockout.

init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    ...
    if (allBindings.has('selectedOptions')) {
        var selectedOptions = allBindings.get('selectedOptions');
        if (ko.isObservable(selectedOptions)) {
            ko.computed({
                read: function () {
                    selectedOptions();

                    // Added to handle knockout binding to an object...not just a value
                    // multiselect needs the selected property on the options, else it wont show them on refresh
                    if ((config.optionsKey !== undefined) &&
                        (config.optionsKey !== null) &&
                        (config.optionsKey.length > 0) &&
                        (config.observableKey !== undefined) &&
                        (config.observableKey !== null) &&
                        (config.observableKey.length > 0)) {
                        var _optionsKey = config.optionsKey;
                        var _observableKey = config.observableKey;
                        ko.utils.arrayForEach(selectedOptions(), function (selectedOption) {
                            $("option[" + _optionsKey + "='" + selectedOption[_observableKey]() + "']", $element).prop('selected', true);
                        })
                    }

                    setTimeout(function () {
                        $element.multiselect('refresh');
                    }, 1);
                },
                disposeWhenNodeIsRemoved: element
            }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
        }
    }
    ...

Selanjutnya saya harus memodifikasi fungsi createOptionValue di bootstrap-multiselect.js untuk terlebih dahulu menggunakan kunci ini sebagai nilai yang ditetapkan dalam item daftarnya:

createOptionValue: function (element) {
    ...

    var value = $element.val();
    // Added to handle knockout binding to an object...not just a value
    if ((this.options.optionsKey !== undefined) && (this.options.optionsKey !== null) && (this.options.optionsKey.length > 0)) {
        var key = $element.attr(this.options.optionsKey);
        if ((key !== undefined) && (key !== null) && (key.length > 0)) {
            value = key;
        }
    }

    ...
}

Terakhir saya harus memodifikasi fungsi getOptionByValue di bootstrap-multiselect.js untuk menemukan elemen opsi berdasarkan atribut ini alih-alih nilai:

getOptionByValue: function (value) {
    var valueToCompare = value.toString();

    // Added to handle knockout binding to an object...not just a value
    if ((this.options.optionsKey !== undefined) && (this.options.optionsKey !== null) && (this.options.optionsKey.length > 0)) {
        var opt = $("option[" + this.options.optionsKey + "='" + valueToCompare + "']", this.$select).first();
        if( (opt !== undefined) && (opt !== null) ) {
            return $(opt);
        }
    }

    var options = $('option', this.$select);

    for (var i = 0; i < options.length; i = i + 1) {
        var option = options[i];
        if (option.value === valueToCompare) {
            return $(option);
        }
    }
},
question

Semua 3 komentar

Terima kasih, akan menyertakan ini di FAQ! Saya yakin ini juga bermanfaat bagi pengguna lain.

Terima kasih atas tip ini - saya mencoba menyelesaikan pengikatan untuk memilih objek juga dan penulisan ini sangat membantu. Satu-satunya hal yang harus saya lakukan selain kode @APM3 adalah juga mengisi atribut "nilai" dari opsi saya di fungsi SetOptionKey:

self.SetOptionKey = function (option, item) { ko.applyBindingsToNode(option, { attr: { "data-key": item.Value } }, item); ko.applyBindingsToNode(option, { attr: { "value": item.Value } }, item); }

Terima kasih sekali lagi untuk tulisan ini.

Lihat Inti untuk pengikatan knockout objek yang didukung. Ganti saja pengikatan aktual dari file bootstrap-multiselect.js. Dalam kode ini Anda tidak perlu memasukkan vm Anda untuk mengatur opsi.

//Just like this one
myVM.SetOptionKey = function ( option, item ) {
    ko.applyBindingsToNode( option, { attr: { "data-key": item.Key } }, item );
};

Saya menambahkan preprocess ke binding untuk secara implisit menambahkan optionsAfterRender .

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

patrickracicot picture patrickracicot  ·  11Komentar

andriijas picture andriijas  ·  8Komentar

Furgas picture Furgas  ·  8Komentar

dturakhia picture dturakhia  ·  11Komentar

jm21 picture jm21  ·  13Komentar