Knockoutjs - 添加到嵌套集合而不更新UI

时间:2013-05-10 08:37:02

标签: knockout.js ko.observablearray

我有一个视图模型,它有几层嵌套的observableArrays。

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

一旦我拥有特定的vmDictionary对象,我需要获取特定的vmConcept对象,该对象是我要添加到的vmTermGroup的父对象。我有一个这个vmConcept的ID,我可以用它来检索它:

var concept;
for (var c = 0; c < dict.Concepts().length; c++) {
    if (dict.Concepts()[c].ID() == conceptId) {
        concept = dict.Concepts()[c];
    }
}

在vmConcept视图模型中,我有一个函数AddTerm。此函数通过检查每个vmTermGroup的Language.ID属性来确定需要哪个vmTermGroup。

当获得匹配的vmTermGroup时,函数push将新的vmTerm作为该vmTermGroup的条款observableArray。

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

但是,当我向vmConcept实例添加新的vmTerm实例时,UI不会更新以显示它。我可以在调用AddTerm之前和之后调用vmTermGroup中的vmTerms数量,并显示例如2和3,但视图永远不会更新。

我也试过打电话给self.TermGroups()[i].Terms.valueHasMutated(),但这没什么区别。

我怀疑是在一个或多个级别我绕过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,我担心有人会要求这样做。如果上面的编辑仍然没有帮助,那么我会尝试将它们放在一起,但它会从我的实际工作中完全删除,因此可能不是真正的相似。

1 个答案:

答案 0 :(得分:1)

我采用了不同的方法来解决这个问题:我没有使用jQuery来附加事件,而是通过视图模型循环来查找所需的内部视图模型,我将事件绑定添加到我的Knockout模板并使用它们来调用上下文视图模型中的函数。

这可以说是我从一开始就应该做的事情。