Knockout.js Knockoutjs-添加到嵌套集合而不更新UI
我有一个视图模型,它有好几层嵌套的可观察阵列Knockout.js Knockoutjs-添加到嵌套集合而不更新UI,knockout.js,ko.observablearray,Knockout.js,Ko.observablearray,我有一个视图模型,它有好几层嵌套的可观察阵列 ViewModel - Dictionaries[vmDictionary] - Concepts[vmConcept] - TermGroups[vmTermGroup] - Language - Terms[vmTerm] 现在,我希望将vmTerm实例(Term对象的视图模型)添加到vmTermGroup的特定实例中,并自动更新UI
ViewModel
- Dictionaries[vmDictionary]
- Concepts[vmConcept]
- TermGroups[vmTermGroup]
- Language
- Terms[vmTerm]
现在,我希望将vmTerm实例(Term对象的视图模型)添加到vmTermGroup的特定实例中,并自动更新UI
为了实现这一点,我构建了一个返回特定vmDictionary对象的函数:
function vmDictionaries(dicts) {
// other JS removed for brevity
self.Dictionaries = ko.observableArray([]);
self.Get = function (id) {
for (var d = 0; d < self.Dictionaries().length; d++) {
if (self.Dictionaries()[d].ID() == id) {
return self.Dictionaries()[d];
}
}
return null;
};
}
但是,当我将vmTerm的新实例添加到vmConcept实例时,UI不会更新以显示它。我可以console.log在调用AddTerm
之前和之后VMTerm组中vmTerms的数量,例如,它显示2,然后显示3,但视图从未更新
我还尝试包括对self.TermGroups()[I].Terms.valuehassmutated()
的调用,但这没有什么区别
我的怀疑是,在一个或多个级别上,我绕过了Knockout的可观察数组,直接跳入内部(本机)数组,这将阻止Knockout跟踪更改,但我看不出还有什么其他方法可以实现我在这里要做的事情
我知道这是一个相当复杂的例子/问题,但有人知道我如何向这个内部集合添加一个新的vmTerm吗
编辑:以下是正在使用的视图模板
<div id="concept-container" data-bind="foreach: Concepts">
<!-- markup removed for brevity -->
<div data-bind="foreach: TermGroups">
<div>
<div class="language-box" data-bind="text: Language.Title"></div>
<!-- ko foreach: Terms -->
<!-- markup removed for brevity -->
<!-- /ko -->
</div>
</div> <!-- end of foreach: TermGroups -->
</div> <!-- end of foreach: Concepts -->
我要添加的是最里面的foreach:Terms
,它没有更新
至于JsFiddle,我担心有人会问这个问题。如果上面的编辑仍然没有帮助,那么我将尝试将其组合在一起,但它将从我正在进行的实际工作中删除,因此可能不是真实的相似性。我对这个问题采取了不同的方法:不是使用jQuery附加事件,而是通过视图模型循环找到所需的内部视图模型,我将事件绑定添加到敲除模板中,并使用这些模板调用上下文视图模型中的函数
这可以说是我从一开始就应该做的。乍一看,我没有发现您发布的代码中有任何问题。也许包含相关的视图代码会有所帮助?当然,我们最适合帮助您的是repro(例如JSFIDLE)。简化的小提琴会非常有用。同意Jeroen的观点,似乎没有任何问题。然后,我想再次看到vmTermGroup和vmTerm。另外,我要指出的是,循环太多了。您可以使用ko.utils.arrayFirst来选择第一个与您的条件相匹配的项目,而不必循环。一把简化的小提琴可以帮助你把它分解,并看到任何逻辑漏洞!
function vmConcept(concept) {
// other JS removed for brevity
self.TermGroups = ko.observableArray();
for (var i = 0; i < concept.TermGroups.length; i++) {
self.TermGroups.push(new vmTermGroup(concept.TermGroups[i]));
}
self.AddTerm = function (vmTerm) {
// loop through all the TermGroups
for (var i = 0; i < self.TermGroups().length; i++) {
// if this TermGroup.Language matches the vmTerm.Language...
if (self.TermGroups()[i].Language.ID() == vmTerm.Language.ID) {
// ...then add vmTerm to this TermGroup
self.TermGroups()[i].Terms.push(vmTerm);
return true;
}
}
return false;
}.bind(this);
}
<div id="concept-container" data-bind="foreach: Concepts">
<!-- markup removed for brevity -->
<div data-bind="foreach: TermGroups">
<div>
<div class="language-box" data-bind="text: Language.Title"></div>
<!-- ko foreach: Terms -->
<!-- markup removed for brevity -->
<!-- /ko -->
</div>
</div> <!-- end of foreach: TermGroups -->
</div> <!-- end of foreach: Concepts -->