我正在我的asp.net mvc 5应用程序中使用knockoutjs构建一个多步骤表单。
问题是,在绑定期间,我的下拉列表的更改事件正在触发。类似于此问题报告here。
我已经尝试了上面帖子中建议的所有内容,但事件仍然是两次发射。
<div class="row">
<div class="col-md-4">
<div class="form-group">
@Html.LabelFor(model => model.Step1.Country, new { @class = "control-label" })
@Html.DropDownListFor(model => model.Step1.Country, Model.Step1.Countries, new { @class = "select-country", @style = "width: 100%;", data_bind = "value: Model.Step1.Country" })
</div>
</div>
<div class="col-md-4">
<div class="form-group">
@Html.LabelFor(model => model.Step1.State, new { @class = "control-label" })
@Html.DropDownListFor(model => model.Step1.State, Model.Step1.States, new { @style = "width: 100%;", data_bind = "value: Model.Step1.State" })
</div>
</div>
<div class="col-md-4">
<div class="form-group">
@Html.LabelFor(model => model.Step1.City, new { @class = "control-label" })
@Html.TextBoxFor(model => model.Step1.City, new { maxlength = "50", @class = "form-control", data_bind = "value: Model.Step1.City" })
</div>
</div>
</div>
向导插件:
(function ($) {
$.fn.Wizard = function (options) {
//Set the form of the current wizard
var $form = $("#" + options.formId);
var ViewModel = function (d, m) {
var self = this;
self.Model = ko.mapping.fromJS(d, m);
self.Model.GeneralErrors = ko.computed(function () {
return ko.utils.arrayFilter(self.Model.Errors(), function (item) {
return !!item.MemberName;
});
});
self.Model.Step1.Country.subscribe(function (value) {
alert(value);
console.log(value);
});
self.SelectionChanged = function (element) {
}
}
var vm = new ViewModel(options.model, options.mapping);
ko.applyBindings(vm, this[0]);
vm.UpdateOnChange = true;
return this;
};
}(jQuery));
<script type="text/javascript">
$(function () {
$("#WizardWrapper").Wizard({
formId: "WizardForm",
model: @(Html.Raw(Json.Encode(Model))),
url: "/DataCollection/@HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString()/",
mapping: {
create: function (options){
var m = ko.mapping.fromJS(options.data);
return m;
}
}
});
});
</script>
有谁知道如何解决这个问题?
感谢user3297291,
谢谢,添加valueAllowUnset在绑定时停止了事件触发,并在进行选择时触发。
但是,只有一个问题,当点击保存时,事件会在回发期间再次触发。
再次触发该事件 ko.mapping.fromJS(data, self.Model);
在下面的ajax帖子中。
保存活动:
self.Next = function (element) {
var validator = $(element).closest("form").validate();
if ($(element).closest("form").valid()) {
$.ajax({
url: options.url + action,
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: ko.toJSON(self.Model),
success: function (data) {
self.UpdateOnChange = false;
ko.mapping.fromJS(data, self.Model);
self.UpdateOnChange = true;
},
error: function (jqXHR, textStatus, errorThrown) {
}
});
} else {
validator.focusInvalid();
}
}
按钮:
<input data-bind="event: { click: Next.bind($data, $element) }" type="submit" class="btn btn-default btn-prev btn-sky" value="Next" />
更新
为了解决国家/地区更新后订阅再次触发的问题,我使用了solution进行了一些更改。
self.dirty = ko.observable(false);
self.selectedCountry = ko.observable();
self.dirtyCalculations = ko.computed(function () {
var value = self.Model.Step1.Country();
if (value == self.selectedCountry()) {
self.selectedCountry(null);
self.dirty(false);
} else {
self.selectedCountry(value);
self.dirty(true);
}
});
self.Model.Step1.Country.subscribe(function (value) {
if (value != undefined && self.dirty()) {
$.ajax({
url: options.url + "GetState",
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: ko.toJSON(self.Model),
traditional: true,
success: function (data) {
self.UpdateOnChange = false;
ko.mapping.fromJS(data, self.Model);
self.UpdateOnChange = true;
}
});
} else {
self.resetDirtyFlag();
}
});
答案 0 :(得分:1)
简单回答:您可以(错误?)使用valueAllowUnset
绑定。
var VM = function(initial) {
this.selection = ko.observable(initial);
this.updateCount = ko.observable(0);
this.selection.subscribe(function() {
this.updateCount(this.updateCount() + 1);
}, this);
}
ko.applyBindings(new VM(1), document.querySelector(".example1"));
ko.applyBindings(new VM(2), document.querySelector(".example2"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="example1">
<h1>with valueAllowUnset</h1>
<select name="" id="" data-bind="value: selection, valueAllowUnset: true">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
<div>
Updates: <span data-bind="text: updateCount"></span>
</div>
</div>
<div class="example2">
<h1>without valueAllowUnset</h1>
<select name="" id="" data-bind="value: selection">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
<div>
Updates: <span data-bind="text: updateCount"></span>
</div>
</div>
替代解决方案:我建议使用options
绑定通过knockout而不是MVC呈现您的选项。它使客户端调试变得容易一些。但这可能是个人偏好。