2013-03-01 116 views
16

我堅持什麼必須是一個簡單的修復。我使用嵌套視圖模型的knockout.js,除了我的刪除功能無法正常工作外,它們看起來都很好。它似乎是正確綁定的,但是當我點擊刪除時它不會被解僱。挖空嵌套視圖模型

爲什麼嵌套視圖模型?長話短說,但基本上很多東西都需要在一個頁面上!

所以這裏是代碼:

HTML

<section class="mini-form-container"> 
    <form data-bind="submit: repeatGuest.addDate"> 
     <input type="date" data-bind="value: repeatGuest.previousStay"/> 
     <button type="submit" class="button-secondary ">Add date</button> 
    </form> 
    <div data-bind="foreach: repeatGuest.dates, visible: repeatGuest.dates().length > 0"> 
     <div> 
      <input data-bind="value: date" disabled="disabled" /> 
      <a data-bind="click: $parent.removeDate">Remove</a> 
     </div> 
    </div> 
</section> 

<section> 
    <div data-bind="text: ko.toJSON($data)"></div> 
</section> 

的Javascript

function RepeatGuest() { 
    /// <summary>Child View Model</summary> 
    this.dates = ko.observableArray(); 
    this.previousStay = ko.observable(); 
} 

RepeatGuest.prototype.addDate = function() { 
     var self = this.repeatGuest; 
     if (self.previousStay()) { 
      self.dates.push({ 
       date: self.previousStay() 
      }); 
     } 
    }; 

RepeatGuest.prototype.removeDate = function (date) { 
    this.dates.remove(date); 
} 

function ViewModel() { 
    var self = this; 
    self.repeatGuest = new RepeatGuest(); 
} 
ko.applyBindings(new ViewModel()); 

這裏是我的小提琴:http://jsfiddle.net/6Px4M/2/

那麼爲什麼我的刪除功能不被解僱?

可能側的問題:是嵌套視圖模型採取淘汰賽走錯了路,似乎沒有對這麼多信息?

回答

23

一個像這樣的嵌套模式工作的最佳途徑是使用with結合。你可以這樣做:現在

<div data-bind="with: repeatGuest"> 
    ... 
</div> 

,範圍是你repeatGuest,你可以針對其性能直接綁定。

您的remove函數的問題與this的值以及當時的$parent有關。函數以等於當前範圍的值this執行。當你的remove函數被綁定時,作用域是date陣列中的一個對象。

典型的方式來處理,這是確保你的功能勢必會始終使用this正確的值。這可以在綁定(非常醜陋)來完成,如:

<a data-bind="click: $parent.repeatGuest.removeDate.bind($parent.repeatGuest)">Remove</a> 

更好的選擇是將其綁定在視圖模型,你RepeatGuest構造:

this.removeDate = this.removeDate.bind(this); 

這使得實現活在原型上使用包裝強制正確的值this覆蓋每個實例。另外,如果你不把它放在原型上,那麼你可以使用var self = this;模式,並在處理程序中使用self

http://jsfiddle.net/cNdJj/

+0

我更喜歡'var self = this'模式。對我來說,總是使用'self'比記住綁定函數更容易。它也看起來更乾淨,imo。 – Tyrsius 2013-03-01 17:46:32

+0

這個好東西,來自我的+1,但是有一個更基本的問題,那就是這個函數從原型開始就不會運行。但如果他遵循了所有可以解決的步驟。 – 2013-03-01 17:50:57

+0

@Tyrsius - 我試圖展示如何將這個函數的實現放在原型上。 'self'是一個很好的模式。 – 2013-03-01 18:06:26

4

結合將無法訪問在錯誤的原型功能。您現在綁定到viewModel,而不是RepeatGuest對象。

,如果你把它設置爲本地函數它的工作原理:

http://jsfiddle.net/6Px4M/3/

function ViewModel() { 
    var self = this; 
    self.repeatGuest = new RepeatGuest(); 
    self.removeDate = function (date) { 
     self.repeatguest.dates.remove(date); 
    } 
} 
+0

啊,這就是我原來的樣子。然而,我的viewModel變得很龐大,我試圖重構它的尺寸。有沒有其他方法可以從視圖模型中獲取刪除功能? – 2013-03-01 17:40:18

+0

當然,你總是可以把它拉出來,只需將'self.removeDate'設置爲函數名。 – 2013-03-01 17:47:46

+1

@ RPNiemeyer的解決方案雖然更完整。 – 2013-03-01 18:11:46