2013-03-01 80 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