2015-11-05 78 views
1

我試圖讓一個元素的文本取決於它是否被選中,但我有困難搞清楚如何引用父對象來確定哪些對象被選中。什麼我想工作過更改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>

的價格應該不會顯示在所選擇的元素,但它應該是其他人。

我已經試過什麼:

  • 「dropDownText」 - 非函數變量做工精細,但這並沒有解決問題
  • 「dropDownTextFunction」 - 顯示功能的代碼,在下拉列表中,也沒有辦法讓父對象
  • 「dropDownTextFunction()」 - 導致空選項的文本,又沒有辦法讓父對象
  • 「$ parent.dropDownText」 - 也導致空選項文本

回答

3

這是一個解決方案,但不是我喜歡在我的應用程序中實現的解決方案。

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是可觀的,從而使顯示的文本可以在它的變化進行更新。您的原始代碼中缺少這一點。

我不喜歡的部分必須在選定值發生變化時計算整個列表的可觀察值。

另一種方法是修改的項目對象和認購,這使得它乾淨了一點:

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; 
} 

但是我真的prefere是讓視圖模型處理整個創建和管理項目。你可以用一個函數來創建一個模型,例如model.addItem(name,price)或者其他像additems([{name: '', price:1}, ...])這樣的函數。如果你嘗試這種方式,你會發現實現視圖模型非常清晰和容易,因爲模型需要關心自身及其所有組件。如果你想從其他代碼中使用它,你也可以將模型中的cosntructor公開。

注:var self=this模式簡化與this工作在其他funcions的模型,如計算觀測

+0

感謝完整的答案,並self'的'澄清,我正要詢問!我實際上正在處理的模型排除了最後一個('addItem')解決方案,但第二個(替代方案)將會很好。 –

+1

現在你已經提到了,如果你閱讀ko計算過的文檔,你會發現自己作爲'calculate'的第二個參數傳遞,這樣它就可以在提供的函數體中作爲'this'訪問。在JavaScript中,'this'很難處理,因爲'this'的值取決於你如何調用函數:通常'this'指的是你調用該函數的對象。另外你可以用'apply'來改變'this'的值:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply – JotaBe

相關問題