c# - select change event fires during binding -
i'm building multi-step form using knockoutjs in asp.net mvc 5 application.
the problem is, during binding, change event dropdown firing. similar issue reported here.
i have tried suggested in post above, event still firing twice.
<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>
wizard plugin:
(function ($) { $.fn.wizard = function (options) { //set form of 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>
does know how can fix this?
thanks user3297291,
thanks, adding valueallowunset stopped event firing when binding , fires when selection made.
however, 1 problem,the event fires again during postback when save click. event triggered again by
ko.mapping.fromjs(data, self.model);
in ajax post below.
save event:
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(); } }
button:
<input data-bind="event: { click: next.bind($data, $element) }" type="submit" class="btn btn-default btn-prev btn-sky" value="next" />
update:
in order fix issue subscription triggering again after country updated, used solution few changes.
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(); } });
simple answer: (mis?)use valueallowunset
binding.
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>
alternative solution: i'd suggest use options
binding render options via knockout instead of mvc. makes bit easier debug client side. might personal preference.
Comments
Post a Comment