【发布时间】:2018-09-01 02:06:33
【问题描述】:
我正在尝试绑定 Bootstrap 日期选择器控件,但没有成功
<input class="form-control" data-bind="datePicker : Observation.ObservationDateTime" type="date" />
到一个 Knockout.js 视图模型。 (这是一个 ASP.NET Core 项目。)其中涉及的活动部件太多,以至于我无法在这种特定情况下隔离问题。 我想要实现的是一个简单的双向绑定:viewmodel 中的日期填充到 datepicker 控件中;并将表单提交的日期发送回视图模型/控制器。
我可以验证日期是否已成功传递给 Knockout 视图模型。为了跟踪它的价值,我目前正在将它作为文本打印在页面上:
<div>Viewmodel date as text: <span data-bind="text:Observation.ObservationDateTime"></span></div>
呈现如下:
我的研究表明,(1) 域模型、(2) 服务器端视图模型、(3) 客户端 (Knockout) 视图模型和 (4) 视图本身中的设置都很重要。所以我粘贴了下面每个的相关代码:
领域模型:
[Required]
//[Display(Name = "Date/Time")]
//[DisplayFormat(DataFormatString = "{0:dddd, dd/MM/yyyy HH:mm}", ApplyFormatInEditMode = true)]
[DataType(DataType.Date)]
public DateTime ObservationDateTime { get; set; }
服务器视图模型/控制器:
Observation = new Observation() { ObservationDateTime = _systemClock.Now },
Client Knockout.js 视图模型
我尝试过各种绑定处理程序。目前(见位开始'ko.bindingHandlers.datepicker':
CreateObservationViewModel = function (data) {
var self = this;
ko.mapping.fromJS(data, observedSpeciesMapping, self);
ko.bindingHandlers.selectPicker = {
init: function (element, valueAccessor, allBindings) {
$(element).selectpicker('render');
}
};
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
$(element).datepicker(options);
//when a user changes the date, update the view model
ko.utils.registerEventHandler(element, "changeDate", function (event) {
var value = valueAccessor();
if (ko.isObservable(value)) {
value(event.date);
}
});
},
update: function (element, valueAccessor) {
var widget = $(element).data("datepicker");
//when the view model is updated, update the widget
if (widget) {
widget.date = ko.utils.unwrapObservable(valueAccessor());
if (widget.date) {
widget.setValue();
}
}
}
};
Razor 视图 datepicker Bootstrap 控件:
<div class="form-group">
<label class="control-label" for="Observation.ObservationDateTime">Date:</label>
<input class="form-control" data-bind="datePicker : Observation.ObservationDateTime" type="date" />
<div>Viewmodel date as text: <span data-bind="text: Observation.ObservationDateTime"></span></div>
</div>
我认为问题出在 Knockout 视图模型中的 datepicker bindingHandler 上。但是,尽管进行了数小时的修补,我还没有解决它。有什么想法或建议吗?
更新 整个视图模型
CreateObservationViewModel = function (data) {
var self = this;
ko.mapping.fromJS(data, observedSpeciesMapping, self);
ko.bindingHandlers.selectPicker = {
init: function (element, valueAccessor, allBindings) {
$(element).selectpicker('render');
}
};
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
$(element).datepicker(options);
//when a user changes the date, update the view model
ko.utils.registerEventHandler(element, "changeDate", function (event) {
var value = valueAccessor();
if (ko.isObservable(value)) {
value(event.date);
}
});
},
update: function (element, valueAccessor) {
//when the view model is updated, update the widget
var value = ko.unwrap(valueAccessor());
$(element).val(value).datepicker("update");
}
};
self.addObservedSpecies = function () {
var observedSpecies = new ObservedSpeciesViewModel({ Id: 0, BirdId: 0, Quantity: 1 });
self.ObservedSpecies.push(observedSpecies);
};
self.removeObservedSpecies = function () {
if (self.ObservedSpecies().length > 1)
self.ObservedSpecies.pop();
};
self.disableSubmitButton = ko.observable(false);
self.Total = ko.computed(function () {
var total = 0;
total += self.ObservedSpecies().length;
return total;
}),
self.post = function () {
self.disableSubmitButton(true);
if (self.ObservedSpecies().length < 1) {
// ToDo: Implement proper client-side validation of the Observed Species collection
alert("You must choose at least one observed bird species");
self.MessageToClient("You must choose at least one observed bird species...");
self.disableSubmitButton(false);
return;
}
$.ajax({
url: "/Observation/Post/",
type: "POST",
data: ko.toJSON(self),
headers:
{
"content-type": "application/json; charset=utf-8"
},
success: function (data) {
var obj = JSON.parse(data);
if (obj.IsModelStateValid === false) {
self.MessageToClient(obj.MessageToClient);
}
else {
window.location.replace("./Index/");
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
self.disableSubmitButton(false);
if (XMLHttpRequest.status === 400) {
$('#MessageToClient').text(XMLHttpRequest.responseText);
}
else {
$('#MessageToClient').text('The web server had an error. The issue has been logged for investigation by the developer.');
}
}
});
};
};
var observedSpeciesMapping = {
'ObservedSpecies': {
key: function (obsevedSpecies) {
return ko.utils.unwrapObservable(obsevedSpecies.Id);
},
create: function (options) {
return new CreateObservationViewModel(options.data);
}
}
};
ObservedSpeciesViewModel = function (data) {
var self = this;
ko.mapping.fromJS(data, observedSpeciesMapping, self);
};
剃刀视图 sn-p
@section scripts{
<script src="~/js/knockout-3.4.2.js"></script>
<script src="~/js/knockout.mapping-latest.js"></script>
<script src="~/js/jqueryvalidate.js"></script>
<script src="~/js/jquery-validate.bootstrap-tooltip.js"></script>
<script src="~/js/createobservationviewmodel.js"></script>
<script type="text/javascript">
var createObservationViewModel = new CreateObservationViewModel(@Html.Raw(data));
ko.applyBindings(createObservationViewModel);
</script>
}
【问题讨论】:
标签: asp.net-core knockout.js bootstrap-datepicker