0

我有一个视图模型,它有几层嵌套的 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);
}

但是,当我将 vmTerm 的新实例添加到 vmConcept 实例时,UI 不会更新以显示它。我可以在调用之前和之后 console.log 记录 vmTermGroup 中的 vmTerms 数量,AddTerm它显示例如 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,我担心有人会要求这个。如果上面的编辑仍然没有帮助,那么我会尝试将一个放在一起,但它会与我实际正在进行的工作完全不同,因此可能不是真正的相似之处。

4

1 回答 1

1

我对这个问题采取了不同的方法:我没有使用 jQuery 附加事件,然后遍历视图模型以找到所需的内部视图模型,而是将事件绑定添加到我的 Knockout 模板并使用这些来调用内部的函数上下文视图模型。

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

于 2013-05-31T14:34:44.020 回答