替换observableArray的内容后重置select元素

时间:2013-03-07 21:49:22

标签: knockout.js

我尝试创建一个功能,其中有两个(或更多)不同的元素数组,例如:

var cities1 = ["Paris", "London", "Warsaw", "Moscow"];
var cities2 = ["Rome", "Paris", "Berlin", "Amsterdam"];

我可以将它们分配给observableArray,它被绑定到select元素。问题是当我在这些数组中有一个共同的元素时,就像在这个例子中:'Paris'。当我选择'Paris'然后将observableArray中的数据从cities1切换到cities2时,我不会得到选择被更改的信息。

请检查我准备说明问题的小提琴:http://jsfiddle.net/zbkkzdsp/3upSH/ 你是否知道如何在observableArray中切换数据导致select元素中的'resetting'选择?

1 个答案:

答案 0 :(得分:1)

迈克尔·贝斯特指出,城市实际上并没有改变。如果您的城市本身就是视图模型,那么您所描述的内容将自动发生。

但是,由于您只有原语,因此您需要明确告诉viewmodel在数组更改时“清除”city的当前值。然后它会自动选择第一个元素。

您可以通过在点击事件中将self.City设置为'',或订阅self.City.Available并将self.City设置为''来执行此操作。您还需要确保将订阅更新为self.City,以便在更新后的值为''时不提醒。

此外,我将click事件中的一些重复功能移至第三个功能,并使两个click函数代理此功能。您的click函数执行完全相同的操作,只使用不同的数据集,因此这消除了一些代码重复。 ATM似乎是无聊的,因为它只有一行开始,但如果你为City更新添加更多功能,这将帮助你减少错误并更快地进行更改。

我在以下代码示例中提供了清除City值的两种方法,并注释掉了非订阅版本,以供参考。

var cities1 = ["Paris", "London", "Warsaw", "Moscow"];
var cities2 = ["Rome", "Paris", "Berlin", "Amsterdam"];

function MyViewModel() {
    var self = this;

    self.City = ko.observable();
    self.City.Available = ko.observableArray();

    self.City.subscribe(function (newValue) {
        if(newValue != '') {
          alert('City has changed to ' + newValue);
        }
    });

    self.City.Available.subscribe(function(newValue) {
       self.City(''); 
    });

    self.click1 = function () {
        self.loadCityList(cities1);
    };

    self.click2 = function () {
        self.loadCityList(cities2);
    };

    self.loadCityList = function(cityList) {
        // clear city w/o subscription
        //self.City('');
        self.City.Available(cityList);        
    }


};

ko.applyBindings(new MyViewModel());

作为一个分页记录,如果您想要允许空字符串用于城市名称,或者只是想要一个更强大的方法来在城市被清除时抑制更改警报,您可以向城市添加一个子观察点并在它之间切换真假。如果你这样做,我会建议添加一个“clearCity”函数来封装所有这些逻辑。 EX

function MyViewModel() {
    ...
    self.City.isLoading = ko.observable(false);

    self.City.subscribe(function (newValue)) {
        if(self.City.isLoading()) {
            self.City.isLoading(false);
        } else {
            alert('City has changed!');
        }
    });

    ...

    //could also put this on city as self.City.clearCity
    self.clearCity = function() {
        self.City.isLoading(true);
        self.City('');
    }

    ...

}