Knockoutjs databind с jquery-ui datepicker
Я использую jQuery UI datepicker. Введенное им поле ввода HTML в настоящее время подключено к KnockoutJS в качестве dependObservable, но когда его значение задано в viewmodel, datepicker теряет свой формат.
Как мне это сделать и не потерять формат? Я бы хотел, чтобы viewModel не знал, что это jQuery datepicker.
Ответы
Ответ 1
Вы можете написать настраиваемую привязку, которая устанавливает дату в поле, используя API datepicker, а также устанавливает значение вашего наблюдаемого, правильно прочитав дату.
Пользовательская привязка может выглядеть так:
ko.bindingHandlers.datepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().datepickerOptions || {},
$el = $(element);
//initialize datepicker with some optional options
$el.datepicker(options);
//handle the field changing
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),
current = $el.datepicker("getDate");
if (value - current !== 0) {
$el.datepicker("setDate", value);
}
}
};
Вы бы использовали его как:
<input data-bind="datepicker: myDate, datepickerOptions: { minDate: new Date() }" />
datepickeroptions
будет необязательным и может включать все, что вы хотите передать в вызов datepicker()
.
Кроме того, предполагается, что вы используете наблюдаемый для даты. Связывание должно сделать немного больше работы, если вы хотите сделать одностороннюю привязку с не наблюдаемым, но это маловероятно.
Пример здесь: http://jsfiddle.net/rniemeyer/NAgNV/
Ответ 2
Мне пришлось внести небольшое изменение в код RP Niemeyer для работы в моем коде с использованием параметра dateFormat, заменив
$(element).datepicker("getDate")
С
$(element).val()
Таким образом, форматированная версия даты была правильно размещена под капотом.
Ответ 3
Я использовал код RP Niemeyer, помеченный как ответ выше, но поскольку я его использовал, я внес несколько небольших изменений в него. Я думал, что отправлю сюда. Может быть, это поможет другим. Это почти то же самое, единственное отличие состоит в том, что если элемент имеет значение при загрузке страницы, то он сохранит свое значение. Кроме того, я сделал переменную $elem
так, что будет меньше обработки $(element)
, которую должен выполнить jQuery.
ko.bindingHandlers['jqDatePicker'] = {
'init': function(element, valueAccessor, allBindingsAccessor) {
/* Initialize datepicker with some optional options */
var options = allBindingsAccessor().jqDatePickerOptions || {},
prop = valueAccessor(),
$elem = $(element);
prop($elem.val());
$elem.datepicker(options);
/* Handle the field changing */
ko.utils.registerEventHandler(element, "change", function () {
prop($elem.datepicker("getDate"));
});
/* Handle disposal (if KO removes by the template binding) */
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$elem.datepicker("destroy");
});
},
'update': function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
$elem = $(element),
current = $elem.datepicker("getDate");
if (value - current !== 0) {
$elem.datepicker("setDate", value);
}
}
};
Ответ 4
Образцы datepicker выше изменяют формат даты в модели view из Формат WCF в формат даты JavaScript, когда пользователь выбирает новую дату от элемента управления datepicker.
В моем случае я передавал дату обратно в службу WCF и не принимал десериализованную дату JavaScript, ей нужна дата в формате WCF. Я изменил приведенный выше script так, чтобы он сохранял дату в viewmodel в формате WCF, чтобы он мог быть отправлен обратно на сервер в этом формате.
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).datepicker("getDate"));
// store the date in 'WCF String format"
var tempdate=$(element).datepicker("getDate");
var tempdatestr="/Date("+tempdate.getTime()+")/";
observable(tempdatestr);
});
//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);
}
}
};
Ответ 5
Вот что сработало для моего конкретного набора обстоятельств. Я запускаю достаточно новую версию MVC, которую наборщик данных по умолчанию datetime отображает в ISO 8601 (см. В кошмар, который является датами JSON. Кроме того, JSON.NET и веб-API ASP.NET). Мои привязки не не записываются непосредственно в подборщик даты, а вместо этого в атрибут "значение" тега ввода.
Кроме того, отметим, что я использую date.js
ko.bindingHandlers.dateValue = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor(),
allBindings = allBindingsAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
var pattern = allBindings.datePattern || 'MM/dd/yyyy';
var date = Date.parse(valueUnwrapped)
$(element).val(date.toString(pattern));
},
init: function(element, valueAccessor, allBindingsAccessor) {
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
var date = Date.parse($(element).val());
observable(date.toString("yyyy-MM-ddThh:mm:ss"));
});
}
}
Связывание выглядит следующим образом:
<input class="date" type="text" data-bind="dateValue: SomeViewModelDate" />
И код JavaScript, чтобы включить datepicker:
$(document).ready(function () {
$('.date').datepicker({ dateFormat: "mm/dd/yy" });
});
Ответ 6
Одним из решений является форматирование даты самостоятельно в функции dependObservable. Поэтому вы должны возвращать что-то вроде return viewModel.someOtherObservable()
в функции. Отформатируйте возвращаемое значение.
Если вы включите свой код, я могу объяснить больше.
Ответ 7
Форматирование даты (в мм/дд/гггг) внутри зависимогоОбсервива - это именно то, что мне было интересно, как это сделать. Я напишу немного своего кода, если вы можете помочь, Питер Мортенсен и/или nEEBz.
<div data-bind="with: technology">
<div class="titleblock">
<label><b>End of Life Date</b></label>
<Input type="text" class="ui-datepicker" id="datepicker" data-bind="value: END_OF_LIFE_DATE"/>
</div>
</div>
в ViewModel - технологияdetail.js:
var technology = ko.observable();
в Активировать:
return dataContext.getTechnologyById(currentTechnologyId, technology);
Это отображает дату, которая выглядит так в текстовом поле: Wed Jan 29 19:00:00 EST 2014, но
Я хочу, чтобы он просто показывал: 01/29/2014. Я использую этот параметр datepicker - dateFormat: "mm/dd/yy", но он не влияет на отображаемое начальное значение.
Мне удалось отформатировать его с помощью момента, и он отлично работает для отображения текущего значения базы данных, но, похоже, он прерывает привязку к наблюдаемому, потому что он больше не будет обновлять SAVE.
<Input type="text" class="ui-datepicker" id="datepicker" data-bind="value: moment(END_OF_LIFE_DATE()).format('MM/DD/YYYY')" />