Saya mencoba menggunakan KnockoutJS dengan jQuery UI. Saya memiliki elemen input dengan datepicker terpasang. Saat ini saya sedang berlari knockout.debug.1.2.1.js
dan sepertinya event perubahan tidak pernah tertangkap oleh Knockout. Elemennya terlihat seperti ini:
<input type="text" class="date" data-bind="value: RedemptionExpiration"/>
Saya bahkan mencoba mengubah valueUpdate
jenis acara tetapi tidak berhasil. Sepertinya Chrome menyebabkan focus
peristiwa tepat sebelum nilai berubah, tetapi IE tidak.
Apakah ada metode Knockout yang "memasang kembali semua ikatan"? Saya secara teknis hanya perlu nilai diubah sebelum saya mengirimkannya kembali ke server. Jadi saya bisa hidup dengan solusi seperti itu.
Saya pikir masalahnya adalah kesalahan datepicker, tetapi saya tidak tahu bagaimana cara memperbaikinya.
Ada ide?
sumber
Ini adalah versi jawaban RP Niemeyer yang akan bekerja dengan skrip validasi sistem gugur yang ditemukan di sini: http://github.com/ericmbarnard/Knockout-Validation
ko.bindingHandlers.datepicker = { init: function (element, valueAccessor, allBindingsAccessor) { //initialize datepicker with some optional options var options = allBindingsAccessor().datepickerOptions || {}; $(element).datepicker(options); //handle the field changing ko.utils.registerEventHandler(element, "change", function () { var observable = valueAccessor(); observable($(element).val()); if (observable.isValid()) { observable($(element).datepicker("getDate")); $(element).blur(); } }); //handle disposal (if KO removes by the template binding) ko.utils.domNodeDisposal.addDisposeCallback(element, function () { $(element).datepicker("destroy"); }); ko.bindingHandlers.validationCore.init(element, valueAccessor, allBindingsAccessor); }, update: function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); //handle date data coming via json from Microsoft if (String(value).indexOf('/Date(') == 0) { value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1"))); } current = $(element).datepicker("getDate"); if (value - current !== 0) { $(element).datepicker("setDate", value); } } };
Perubahan pada penangan peristiwa perubahan untuk meneruskan nilai yang dimasukkan dan bukan tanggal ke skrip validasi terlebih dahulu, kemudian hanya menyetel tanggal ke yang dapat diamati jika valid. Saya juga menambahkan validationCore.init yang diperlukan untuk pengikatan khusus yang dibahas di sini:
http://github.com/ericmbarnard/Knockout-Validation/issues/69
Saya juga menambahkan saran rpenrose untuk blur pada perubahan untuk menghilangkan beberapa skenario datepicker yang mengganggu.
sumber
Saya telah menggunakan pendekatan yang berbeda. Karena knockout.js tampaknya tidak mengaktifkan peristiwa saat berubah, saya telah memaksa datepicker untuk memanggil change () untuk inputnya setelah ditutup.
$(".date").datepicker({ onClose: function() { $(this).change(); // Forces re-validation } });
sumber
Meskipun semua jawaban ini menyelamatkan saya dari banyak pekerjaan, tidak satupun dari mereka berhasil sepenuhnya untuk saya. Setelah memilih tanggal, nilai yang diikat tidak akan diperbarui. Saya hanya bisa memperbaruinya ketika mengubah nilai tanggal menggunakan keyboard lalu mengklik dari kotak input. Saya memperbaikinya dengan menambahkan kode RP Niemeyer dengan kode syb untuk mendapatkan:
ko.bindingHandlers.datepicker = { init: function (element, valueAccessor, allBindingsAccessor) { //initialize datepicker with some optional options var options = allBindingsAccessor().datepickerOptions || {}; var funcOnSelectdate = function () { var observable = valueAccessor(); observable($(element).datepicker("getDate")); } options.onSelect = funcOnSelectdate; $(element).datepicker(options); //handle the field changing ko.utils.registerEventHandler(element, "change", funcOnSelectdate); //handle disposal (if KO removes by the template binding) ko.utils.domNodeDisposal.addDisposeCallback(element, function () { $(element).datepicker("destroy"); }); }, update: function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); if (typeof(value) === "string") { // JSON string from server value = value.split("T")[0]; // Removes time } var current = $(element).datepicker("getDate"); if (value - current !== 0) { var parsedDate = $.datepicker.parseDate('yy-mm-dd', value); $(element).datepicker("setDate", parsedDate); } } };
Saya menduga meletakkan observable ($ (element) .datepicker ("getDate")); pernyataan dalam fungsinya sendiri dan mendaftarkannya dengan options.onSelect berhasil?
sumber
onSelect
fungsi itu tidak akan menaikkanchange
acara ...Terima kasih untuk artikel ini, saya merasa sangat berguna.
Jika Anda ingin DatePicker berperilaku persis seperti perilaku default JQuery UI, saya sarankan untuk menambahkan blur pada elemen di penangan peristiwa perubahan:
yaitu
//handle the field changing ko.utils.registerEventHandler(element, "change", function () { var observable = valueAccessor(); observable($(element).datepicker("getDate")); $(element).blur(); });
sumber
Saya memecahkan masalah ini dengan mengubah urutan file skrip yang saya sertakan:
<script src="@Url.Content("~/Scripts/jquery-ui-1.10.2.custom.js")"></script> <script src="@Url.Content("~/Scripts/knockout-2.2.1.js")"></script>
sumber
Sama seperti RP Niemeyer, tetapi lebih baik mendukung WCF DateTime, Timezones dan Menggunakan properti JQuery onSelect DatePicker.
ko.bindingHandlers.datepicker = { init: function (element, valueAccessor, allBindingsAccessor) { //initialize datepicker with some optional options var options = allBindingsAccessor().datepickerOptions || {}; var funcOnSelectdate = function () { var observable = valueAccessor(); var d = $(element).datepicker("getDate"); var timeInTicks = d.getTime() + (-1 * (d.getTimezoneOffset() * 60 * 1000)); observable("/Date(" + timeInTicks + ")/"); } options.onSelect = funcOnSelectdate; $(element).datepicker(options); //handle the field changing ko.utils.registerEventHandler(element, "change", funcOnSelectdate); //handle disposal (if KO removes by the template binding) ko.utils.domNodeDisposal.addDisposeCallback(element, function () { $(element).datepicker("destroy"); }); }, update: function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); //handle date data coming via json from Microsoft if (String(value).indexOf('/Date(') == 0) { value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1"))); } current = $(element).datepicker("getDate"); if (value - current !== 0) { $(element).datepicker("setDate", value); } } };
Nikmati :)
http://jsfiddle.net/yechezkelbr/nUdYH/
sumber
Saya pikir ini bisa dilakukan dengan lebih mudah:
<input data-bind="value: myDate, datepicker: myDate, datepickerOptions: {}" />
Jadi Anda tidak perlu penanganan perubahan manual dalam fungsi init.
Tetapi dalam kasus ini, variabel 'myDate' Anda hanya akan mendapatkan nilai yang terlihat, bukan objek Tanggal.
sumber
Atau, Anda dapat menentukan ini dalam penjilidan:
Memperbarui:
function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()), current = $(element).datepicker("getDate"); if (typeof value === "string") { var dateValue = new Date(value); if (dateValue - current !== 0) $(element).datepicker("setDate", dateValue); } }
sumber
Berdasarkan solusi Ryan, myDate mengembalikan string tanggal standar, yang bukan yang ideal dalam kasus saya. Saya menggunakan date.js untuk mengurai nilainya sehingga itu akan selalu mengembalikan format tanggal yang Anda inginkan. Lihatlah Contoh biola contoh ini .
update: function(element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()), current = $(element).datepicker("getDate"); var d = Date.parse(value); if (value - current !== 0) { $(element).datepicker("setDate", d.toString("MM/dd/yyyy")); } }
sumber
Saya perlu berulang kali memperbarui data saya dari server menemukan ini tetapi tidak cukup menyelesaikan pekerjaan untuk kebutuhan saya berbagi di bawah ini (format tanggal saya / Tanggal (1224043200000) /):
//Object Model function Document(data) { if (String(data.RedemptionExpiration).indexOf('/Date(') == 0) { var newDate = new Date(parseInt(data.BDate.replace(/\/Date\((.*?)\)\//gi, "$1"))); data.RedemptionExpiration = (newDate.getMonth()+1) + "/" + newDate.getDate() + "/" + newDate.getFullYear(); } this.RedemptionExpiration = ko.observable(data.RedemptionExpiration); } //View Model function DocumentViewModel(){ ///additional code removed self.afterRenderLogic = function (elements) { $("#documentsContainer .datepicker").each(function () { $(this).datepicker(); }); }; }
Setelah model diformat dengan benar untuk output, saya menambahkan template dengan dokumentasi knockoutjs :
<div id="documentsContainer"> <div data-bind="template: { name: 'document-template', foreach: documents, afterRender: afterRenderLogic }, visible: documents().length > 0"></div> </div> //Inline template <script type="text/html" id="document-template"> <input data-bind="value: RedemptionExpiration" class="datepicker" /> </script>
sumber
Beberapa orang meminta opsi pemilih data dinamis. Dalam kasus saya, saya memerlukan rentang tanggal dinamis - jadi masukan pertama menentukan nilai min dari yang kedua dan yang kedua menetapkan nilai maksimal untuk yang pertama. Saya menyelesaikannya dengan memperpanjang handler RP Niemeyer. Jadi aslinya:
ko.bindingHandlers.datepicker = { init: function(element, valueAccessor, allBindingsAccessor) { //initialize datepicker with some optional options var options = allBindingsAccessor().datepickerOptions || {}, $el = $(element); $el.datepicker(options); //handle the field changing by registering datepicker's changeDate event ko.utils.registerEventHandler(element, "change", function() { var observable = valueAccessor(); observable($el.datepicker("getDate")); }); //handle disposal (if KO removes by the template binding) ko.utils.domNodeDisposal.addDisposeCallback(element, function() { $el.datepicker("destroy"); }); }, update: function(element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()), $el = $(element); //handle date data coming via json from Microsoft if (String(value).indexOf('/Date(') == 0) { value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1"))); } var current = $el.datepicker("getDate"); if (value - current !== 0) { $el.datepicker("setDate", value); } } };
Saya telah menambahkan dua penangan lagi yang sesuai dengan opsi yang ingin saya ubah:
ko.bindingHandlers.minDate = { update: function(element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()), current = $(element).datepicker("option", "minDate", value); } }; ko.bindingHandlers.maxDate = { update: function(element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()), current = $(element).datepicker("option", "maxDate", value); } };
Dan menggunakannya seperti itu di template saya:
<input data-bind="datepicker: selectedLowerValue, datepickerOptions: { minDate: minValue()}, maxDate: selectedUpperValue" /> <input data-bind="datepicker: selectedUpperValue, datepickerOptions: { maxDate: maxValue()}, minDate: selectedLowerValue" />
sumber
Menggunakan binding kustom yang disediakan di jawaban sebelumnya tidak selalu memungkinkan. Memanggil
$(element).datepicker(...)
membutuhkan waktu yang cukup lama, dan jika Anda memiliki, misalnya, beberapa lusinan, atau bahkan ratusan elemen untuk memanggil metode ini, Anda harus melakukannya "malas", yaitu sesuai permintaan.Misalnya, model tampilan dapat diinisialisasi,
input
s dimasukkan ke DOM, tetapi datepickers terkait hanya akan diinisialisasi ketika pengguna mengkliknya.Jadi, inilah solusi saya:
Tambahkan pengikatan khusus yang memungkinkan untuk melampirkan data arbitrer ke sebuah node:
KO.bindingHandlers.boundData = { init: function(element, __, allBindings) { element.boundData = allBindings.get('boundData'); } };
Gunakan pengikatan ke attcah yang dapat diamati yang digunakan untuk
input
nilai:<input type='text' class='my-date-input' data-bind='textInput: myObservable, boundData: myObservable' />
Dan terakhir, saat menginisialisasi datepicker, gunakan
onSelect
opsinya:$('.my-date-input').datepicker({ onSelect: function(dateText) { this.myObservable(dateText); } //Other options });
Dengan cara ini, setiap kali pengguna mengubah tanggal dengan datepicker, observasi Knockout yang sesuai juga diperbarui.
sumber