敲除嵌套视图模型 [英] Knockout nested view model
问题描述
我坚持必须是一个简单的修复.我正在使用带有嵌套视图模型的knockout.js,除了我的remove 功能无法正常工作外,一切似乎都很好.它似乎绑定正确,但是当我单击删除时它不会被触发.
为什么要嵌套视图模型?说来话长,但基本上很多东西都需要在一页上!
代码如下:
HTML
<form data-bind="提交:repeatGuest.addDate"><input type="date" data-bind="value: repeatGuest.previousStay"/><button type="submit" class="button-secondary">添加日期</button></表单><div data-bind="foreach:repeatGuest.dates,可见:repeatGuest.dates().length>0"><div><input data-bind="value: date" disabled="disabled"/><a data-bind="click: $parent.removeDate">Remove</a>
</节><部分><div data-bind="text: ko.toJSON($data)"></div></节>
Javascript
function RepeatGuest() {///<summary>子视图模型</summary>this.dates = ko.observableArray();this.previousStay = ko.observable();}RepeatGuest.prototype.addDate = function () {var self = this.repeatGuest;如果(self.previousStay()){self.dates.push({日期:self.previousStay()});}};RepeatGuest.prototype.removeDate = 函数(日期){this.dates.remove(date);}函数视图模型(){var self = this;self.repeatGuest = new RepeatGuest();}ko.applyBindings(new ViewModel());
这是我的小提琴:http://jsfiddle.net/6Px4M/2/
那么为什么我的删除功能没有被触发?
可能的问题:嵌套视图模型是否是淘汰赛的错误路径,似乎没有太多关于此的信息?
处理像这样的嵌套模型的最佳方法之一是使用 with
绑定.你可以这样做:
...
现在,范围是您的 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
.
I'm stuck with what must be a simple fix. I am using knockout.js with nested view models, and all seems fine except that my remove function is not working correctly. It appears to be binding correctly, however it is not fired when I click remove.
Why nested view models? Long story, but essentially a lot of stuff is required to be on one page!
So here is the code:
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());
And here is my fiddle: http://jsfiddle.net/6Px4M/2/
So why isn't my remove function getting fired?
Possible side question: is nested view models the wrong path to take in knockout, there doesn't seem to much info on this?
One of the best ways to work with a nested model like this is to use the with
binding. You can do:
<div data-bind="with: repeatGuest">
...
</div>
Now, the scope is your repeatGuest
and you can bind directly against its properties.
The issue with your remove
function is related to the value of this
and who $parent
is at that time. Functions are executed with a value of this
that is equal to the current scope. When your remove function is bound, the scope is one of the objects in the date
array.
The typically way to handle this is to make sure that your function is bound to always use the correct value of this
. This could be done in the binding (very ugly) like:
<a data-bind="click: $parent.repeatGuest.removeDate.bind($parent.repeatGuest)">Remove</a>
A better option is to bind it in the view model, in your RepeatGuest
constructor:
this.removeDate = this.removeDate.bind(this);
This allows the implementation to live on the prototype and overwrites it on each instance with a wrapper that forces the correct value of this
. Alternatively, if you do not put it on the prototype, then you can use the var self = this;
pattern and use self
in the handler.
这篇关于敲除嵌套视图模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!