在绑定期间选择更改事件触发

时间:2016-04-19 06:21:07

标签: c# jquery asp.net asp.net-mvc knockout.js

我正在我的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();
            }
        });

1 个答案:

答案 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呈现您的选项。它使客户端调试变得容易一些。但这可能是个人偏好。