简体   繁体   English

更新数据集时的淘汰赛变更事件触发(取决于下拉列表)

[英]Knockout Change Event Firing when updating data set (dependant dropdowns)

I'm hoping this is just me being a bit of a prune but I am having trouble with the change event firing when I don't want it to. 我希望这只是我的一点修剪,但当我不希望更改事件触发时遇到麻烦。 I will try and keep it short and sharp. 我会尽量保持简短。

I have two drop downs, Country and City. 我有两个下拉菜单,“国家”和“城市”。 both of these are bound as follows: 这两个绑定如下:

<select data-bind="options: Countries, event: { change: IChanged }, value: CountrySelected">
<select data-bind="options: Cities, event: { change: IChanged }, value: CitySelected">

My little view model 我的小视图模型

self.Countries = ko.observableArray([]);
self.Cities = ko.observableArray([]);
self.CountrySelected = ko.observable();
self.CitySelected = ko.observable();

Now my function IChanged() 现在我的函数IChanged()

self.IChanged = function(item) {
    GoGetMyOptions().done(function(response) {
        self.Cities(response);    
    });
}

The problem! 问题!

when calling self.Cities(response); 打电话给self.Cities(response); it triggers the change event on the City drop down, this means that drop down will call the method again. 它会在“城市”下拉菜单上触发更改事件,这意味着下拉菜单将再次调用该方法。

Caveat 警告

I have simplified this, I could have 1 to 80 filters. 我已经简化了这一点,我可以使用1到80个过滤器。 In my code I basically go off and load the drop down options for everything on the right, problem is it calls the change event for everything on the right :O Ideas anyone? 在我的代码中,我基本上关闭并为右侧的所有内容加载下拉选项,问题是它为右侧的所有内容调用了change事件:O有人吗?

A more complicated example (closer to my code 一个更复杂的示例(更接近我的代码

I actually have a filter collection, self.FilterCollection , each filter has the following: 我实际上有一个过滤器集合self.FilterCollection ,每个过滤器都有以下内容:

self.DropDownValues = ko.observableArray([]);
self.SelectedValue = ko.observable();

You can see that when a drop down is selected, it updates the selected value and THEN refreshed the DropDownValues array for all filters to the right. 您可以看到,选择下拉菜单后,它将更新所选值,然后刷新右侧所有过滤器的DropDownValues数组。

In a rather awkward scenario, 在一个比较尴尬的情况下,

  1. A user has a CITY selected 用户已选择一个城市
  2. They select a COUNTRY 他们选择一个国家
  3. The CITY list is update CITY列表已更新
  4. Thus resetting the current value** 从而重置当前值**

Number 4 will trigger a subscription I believe... 我相信4号会触发订阅...

A Full Scenario 完整方案

There are 4 drop downs, A, B, C and D. 有4个下拉菜单,A,B,C和D。

When a user selects a value from A, I will iterate through the remaining drop downs and call getValues , this will then update the DropDownValues observable. 当用户从A中选择一个值时,我将遍历其余下拉菜单并调用getValues ,然后将更新可观察到的DropDownValues

Therefore, I want, 1 UI event to fire saying "the user changed drop down a", I then need to make 3 ajax calls to load B, C and D and update the observable array. 因此,我想触发1个 UI事件,说“用户更改了下拉列表a”,然后我需要进行3个 ajax调用来加载B,C和D并更新可观察数组。

My problem is that when the User selects A, it makes 3 ajax calls correctly but upon setting the value of B it triggers the event... 我的问题是,当用户选择A时,它会正确进行3个Ajax调用,但是在设置B的值时会触发事件...

This then means B will make 2 ajax calls to update C and D. So when a user selects something in drop down A it actually fires: 然后,这意味着B将进行2个Ajax调用来更新C和D。因此,当用户在下拉菜单A中选择某项时,它实际上会触发:

1 UI event, 3 Ajax calls, 1 UI event, 2 ajax calls, 1 UI event, 1 ajax call and then one final UI event. 1个UI事件,3个Ajax调用,1个UI事件,2个ajax调用,1个UI事件,1个ajax调用以及一个最终的UI事件。 So to sumarize, one click by the user makes 4 UI event calls and 6 ajax calls :( 综上所述,用户单击一下即可进行4个UI事件调用和6个ajax调用:(

I've got a gut feeling you've oversimplified to ask the question, but as it stands there are two main points to make about your repro: 我有一种直觉,觉得您对这个问题过于简单了,但是就目前而言,关于您的再现性有两点要点:

  1. You're subscribing to a DOM event. 您正在订阅DOM事件。 No need for that: use a view model based subscription instead. 无需这样做:改为使用基于视图模型的订阅。 It'll give you a lot more control and allow you to unit test it as well. 它会给您更多的控制权,并允许您对其进行单元测试。
  2. You're calling IChanged on changing the Cities dropdown, which makes no sense. 您在更改Cities下拉列表时调用IChanged ,这没有任何意义。 Why update the list of available cities when the user changes that city? 用户更改城市时,为什么要更新可用城市列表?

Anyways, here's a way to prevent the looping update: 无论如何,这是一种防止循环更新的方法:

 function GoGetMyOptions(country) { console.log("Doing ajaxy stuff"); return { done: function(callback) { if (country === "USA") callback(["New York", "LA", "Chicago"]); if (country === "GBR") callback(["London", "Manchester", "Leeds"]); if (country === "GER") callback(["Bonn", "Koln", "Hamburg"]); } }; } function ViewModel() { var self = this; self.Countries = ko.observableArray([]); self.Cities = ko.observableArray([]); self.CountrySelected = ko.observable(); self.CitySelected = ko.observable(); self.CountrySelected.subscribe(function(newVal) { GoGetMyOptions(newVal).done(function(response) { self.Cities(response); }); }); } var vm = new ViewModel(); vm.Countries.push("USA", "GBR", "GER"); ko.applyBindings(vm); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script> <select data-bind="options: Countries, value: CountrySelected"></select> <select data-bind="options: Cities, value: CitySelected"></select> 

As you can see on the console, no Ajax calls would happen when changing the City, only when changing the country. 正如您在控制台上看到的那样,在更改城市时,只有在更改国家时,才会发生Ajax调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM