#asp.net-mvc #date #knockout.js #format
#asp.net-mvc #Дата #knockout.js #формат
Вопрос:
Я использую Asp.Net MVC 4 и Нокаут в форме.
У меня есть ввод даты, который я хочу отформатировать.
В итоге я получил это решение: http://jason-mitchell.com/web-development/binding-dates-using-knockout-moment-js /
Моя проблема в том, что когда я отправляю форму, у меня нет даты, заполненной в опубликованном JSON.
Я думаю, что проблема находится в пользовательском обработчике, но я не могу выяснить: (Событие обновления срабатывает только один раз при загрузке.
Просмотр кода
@Html.TextBoxFor(Function(model) model.EndDate, New With {.data_bind = "date: EndDate"})
Пользовательский код привязки
ko.bindingHandlers.date = {
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
var allBindings = allBindingsAccessor();
// Date formats: http://momentjs.com/docs/#/displaying/format/
var pattern = allBindings.format || 'L';
var output = "";
if (valueUnwrapped !== null amp;amp; valueUnwrapped !== undefined amp;amp; valueUnwrapped.length > 0) {
output = moment(valueUnwrapped).format(pattern);
}
if ($(element).is("input") === true) {
$(element).val(output);
} else {
$(element).text(output);
}
}
};
Код привязки ko
var viewModel = ko.mapping.fromJS(@Html.Raw(Model.ToJson()));
ko.applyBindings(viewModel);
Примечание: формат даты работает так, как ожидалось.
Что я делаю не так? 🙁
Ответ №1:
Не видя вашей ViewModel, я могу только строить предположения. В вашем коде вы привязываете конечную дату непосредственно к текстовому полю:
@Html.TextBoxFor(Function(model) model.EndDate, New With {.data_bind = "date: EndDate"})
Ваша наблюдаемая конечная дата ничего не знает об этом значении. Поэтому, если ваша наблюдаемая конечная дата выглядит примерно так в вашей ViewModel:
this.EndDate = ko.observable();
Тогда он не знает о значении, которое было привязано непосредственно к текстовому полю вашим ASP.NET Код MVC. Поэтому, когда вы применяете свои привязки KO, значение конечной даты, которое было привязано непосредственно к текстовому полю, уничтожается. Если это так, вы можете либо (1) инициализировать наблюдаемую конечную дату непосредственно из значения, привязанного к модели сервера, либо (2) инициализировать наблюдаемую конечную дату косвенно, используя пользовательскую привязку KO, которая инициализирует наблюдаемую конечную дату из значения, которое было привязано непосредственно к текстовому полю.
Пример 1
В этом примере предполагается, что JavaScript находится непосредственно в вашем представлении. Если ваш JavaScript находится в отдельном файле (как это обычно бывает), вам придется передать данные модели в вашу ViewModel, используя другой метод, такой как сериализация JSON на клиенте, прежде чем привязывать вашу ViewModel.
this.EndDate = ko.observable('@Model.EndDate.ToString()');
Пример 2
В этом примере важен последовательный порядок параметров привязки KO. Новая пользовательская привязка должна быть первой привязкой, чтобы это работало правильно:
@Html.TextBoxFor(Function(model) model.EndDate, New With {.data_bind = "initInputFromView: EndDate, date: EndDate"})
И вот код для пользовательской привязки KO:
ko.bindingHandlers.initInputFromView = {
init: function (element, valueAccessor) {
// reads the value stored in the <input> value attribute and initializes the observable with that value
valueAccessor()(element.value);
}
};
Комментарии:
1. Фактически, я заполняю ko ViewModel этой строкой: var ViewModel = ko.mapping.fromJS(@Html.Raw(Model. toJSON())); @Html.Raw(Модель. toJSON())); дайте мне этот Json для конечной даты: «{«Конечная дата»:»2014-12-31T00:00:00″}» С предупреждением (ViewModel. EndDate()); сразу после изменения ViewModel = ko.mapping.fromJS(@Html.Raw(Model. toJSON())); Я получаю «2014-12-31T00:00:00». Поэтому я думаю, что он знает начальное значение. Привязка работает просто отлично, без какой-либо другой привязки «дата»? :/
Ответ №2:
Наконец, я нашел решение!
Пользовательская привязка должна выглядеть так :
ko.bindingHandlers.date = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
ko.bindingHandlers.value.init(element, valueAccessor,
allBindingsAccessor, viewModel, bindingContext);
var value = valueAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
var allBindings = allBindingsAccessor();
// Date formats: http://momentjs.com/docs/#/displaying/format/
var pattern = allBindings.format || 'L';
var output = valueUnwrapped;
if (valueUnwrapped !== null amp;amp; valueUnwrapped !== undefined amp;amp; valueUnwrapped.length > 0) {
output = moment(valueUnwrapped).format(pattern);
}
if ($(element).is("input") === true) {
$(element).val(output);
} else {
$(element).text(output);
}
},
};
Он использует привязку значения по умолчанию плюс мой пользовательский формат даты.
Только при инициализации, потому что обновление управляется с помощью выбора даты, который правильно отформатирован.