根据所选状态

时间:2015-11-05 13:55:00

标签: javascript knockout.js

我试图让元素的文本根据它是否被选中而有所不同,但我很难弄清楚如何引用父对象来确定哪个对象是地选择。

我尝试解决的问题的简化示例:



function Model(items){
    this.items = ko.observableArray(items);
    this.selectedItem = ko.observable();
    this.dropDownText = function(item){
        if(this.selectedItem()===item){
            return item.name;
        }else{
            return item.dropDownText;
        }
    }
}

function Item(name, price){
    this.name=name;
    this.price=price;
    this.dropDownText=name + ' ($' + price + ')';
    this.dropDownTextFunction = function(item){
        return item.name + ' ($' + item.price + ')';
    }
}

var m = new Model([new Item('hammer', 5), new Item('nail', 0.03), new Item('tooth', 0.6)]);
m.selectedItem(m.items()[1]);
ko.applyBindings(m);

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<select data-bind="options: items(), value: selectedItem, optionsText: 'dropDownText'"></select>
<span data-bind="text: selectedItem().price"></span>
&#13;
&#13;
&#13;

价格不应显示在所选元素中,但应该是其他元素。

我尝试过的事情:

  • &#39; dropDownText&#39; - 非功能变量工作正常,但这并没有解决问题
  • &#39; dropDownTextFunction&#39; - 在下拉列表中显示函数的代码,也无法访问父对象
  • &#39; dropDownTextFunction()&#39; - 导致空选项文本,再次无法访问父对象
  • &#39; $ parent.dropDownText&#39; - 也会导致空选项文本

1 个答案:

答案 0 :(得分:3)

这是一个解决方案,但不是我希望在我的ko应用程序中实现的解决方案。

function Model(items){
    var self = this;
    self.items = ko.observableArray(items);
    self.selectedItem = ko.observable();
  
    self.selectedItem.subscribe(function() {
      console.log('Selected');
      items.forEach(function(it) {
        if (it === self.selectedItem()) {
          it.dropDownText(it.name);
        } else {
          it.dropDownText(it.name + ' ($' + it.price + ')');
        }
      });
    });
  
    
    return self;
}

function Item(name, price){
    this.name=name;
    this.price=price;
    this.dropDownText= ko.observable(name + ' ($' + price + ')');
}

var m = new Model([new Item('hammer', 5), new Item('nail', 0.03), new Item('tooth', 0.6)]);
m.selectedItem(m.items()[1]);
ko.applyBindings(m);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<select data-bind="options: items(), value: selectedItem, optionsText: 'dropDownText'"></select>
<span data-bind="text: selectedItem().price"></span>

一个完全必要的事情是dropDownText是可观察的,因此显示的文本可以在更改时更新。原始代码中缺少这个。

我不喜欢的部分是,只要选定的值发生变化,就必须计算整个列表的observable。

另一种方法是修改项目对象和订阅,这使它更清洁:

function Model(items){
    var self = this;
    self.items = ko.observableArray(items);
    self.selectedItem = ko.observable();
    self.selectedItem.subscribe(function() {
      items.forEach(function(it) {
        it.selected(it === self.selectedItem())
      });
    });    
    return self;
}

function Item(name, price){
    var self = this;
    self.name = name;
    self.price = price;
    self.selected = ko.observable(false);
    self.dropDownText = ko.computed(function() {
      return this.selected()
          ? this.name : this.name + ' ($' + this.price + ')';
    },self);
    return self;
}

但我真正喜欢的是让viewmodel处理项目的整个创建和管理。您可以使用可以像model.addItem(name,price)或其他类似additems([{name: '', price:1}, ...])调用的函数创建一个模型。如果你尝试这条路径,你会发现实现视图模型非常简单明了,因为模型可以自行处理它及其所有组件。如果要从其他代码中使用它,也可以在模型中公开cosntructor。

注意:var self=this模式简化了在模型中的其他功能中使用this,如计算的observables