同一视图/模型在一个母版页上的多个实例-元素id



我有一个小的,简单的视图&显示一些数字和图表的视图模型。我被要求提供一个"并排"视图,这样最多可以并排显示6个实例。

看起来有点天真,我只是在我的视图中这样做了:

<div class="container acd">
    <div class="row">
        <div class="col-md-2">
        <div data-bind="compose: { model: acd1}"></div>
        </div>
        <div class="col-md-2">
        <div data-bind="compose: { model: acd2 }"></div>
        </div>
        <div class="col-md-2">
        <div data-bind="compose: { model: acd3 }"></div>
        </div>
        <div class="col-md-2">
        <div data-bind="compose: { model: acd4 }"></div>
        </div>
        <div class="col-md-2">
        <div data-bind="compose: { model: acd5 }"></div>
        </div>
        <div class="col-md-2">
        <div data-bind="compose: { model: acd6 }"></div>
        </div>
    </div>
 </div>

和这个在视图模型:

var acd1 = new acd({ header: 'Article 1'});
var acd2 = new acd({ header: 'Article 2'});
var acd3 = new acd({ header: 'Article 3'});
var acd4 = new acd({ header: 'Article 4'});
var acd5 = new acd({ header: 'Article 5'});
var acd6 = new acd({ header: 'Article 6'});

…其中"添加"是参考"需要"在我的视图模型,链接到独立视图&viewmodel .

这似乎一开始工作,我有6个实例并排在页面上与不同的标题如上所述。

然而,当我开始实际启动一些加载事件,其中一个节是数据绑定到一个可观察对象,控制它是否可见,似乎没有足够的分离实例,因为在第一个实例中改变一个下拉菜单实际上揭示了第6节的节!

当我通过chrome开发工具检查页面上的元素时,所有的div id都是相同的,所以我想有一个基本的问题,我想在这里实现什么?我认为,通过在母版页中创建"新"实例,它将创建具有自我意识的独立实例,以便在传递参数/更新时,它们会知道引用自己的id实例,但它不会出现。

谁有任何指示,试图帮助我在这里,请吗?

母版页视图模型:

define(['services/datacontext', 'viewmodels/articleComparisonDetail'], function (datacontext, acd) {
    var acd1 = new acd({ header: 'Article 1'});
    var acd2 = new acd({ header: 'Article 2'});
    var acd3 = new acd({ header: 'Article 3'});
    var acd4 = new acd({ header: 'Article 4'});
    var acd5 = new acd({ header: 'Article 5'});
    var acd6 = new acd({ header: 'Article 6'});
    var acdMaster = {
        acd1: acd1,
        acd2: acd2,
        acd3: acd3,
        acd4: acd4,
        acd5: acd5,
        acd6: acd6
    };
    return acdMaster;
});

为了添加更多信息,我在"var acdMaster =…"行上放置了一个调试停止点,在那一刻,acd1-6似乎是独立和独立的视图模型,"header"属性设置为我使用的6个单独的值。然而,各个详细信息视图中的输入框似乎并没有链接到特定的实例。

add "detail"视图(简化):

      <div id="acdWrapper">
        <section id="acd">
            <div class="acdArticleCode" data-bind="text: header"></div>
                <div class="formGrid">
                    <input autocomplete="off"  data-bind="typeahead: { name: 'sectionNames', highlight: true, source: articleList}, value: artCode""/>
                </div>
                <!-- ko if: articleLoaded() == true -->
                <div id="articleSelected" data-bind="visible: articleLoaded()">
                    <div class="formGrid resultsTable">
                        <div class="formRow">
                            <div class="formCell">
                                <label>Article Weight:</label>
                            </div>
                            <div class="formCell text-right">
                                <span data-bind="numericText: loadedArticle().totalArticleWeight, precision: 2"></span>
                            </div>
                        </div>

                 ...

         </div>
        <!-- /ko -->
         <div id="articleNotSelected" data-bind="visible: !articleLoaded()">
            <p>Type a minimum of 2 characters into text box to see list of articles</p>
        </div>
 </section>

…和视图模型(也简化了)

define(['plugins/dialog', 'knockout', 'config', 'services/datacontext'], function (dialog, ko, config, datacontext) {
    var acdvm = function (params) {
        var self = this;
        self.content = ko.observable();
        self.header = ko.observable(params.header);
        self.loadedArticle = ko.observable(); //contains entity object for display
        self.articleLoaded = ko.observable(false); //is article loaded true/false
        self.articleList = ko.observableArray([]); //holds list of matching articles from search
        self.selectedRow = ko.observable('e1');
        self.chartID = ko.computed(function () {
            var str = self.header() + "_chart";
            return str.replace(" ","");
        }, this, { deferEvaluation: true });
        self.displayPrecision = ko.observable(6);
        self.artCode = ko.observable('');
    };
    return acdvm;
});

编辑2 所以我进一步调查。我说:

function externalActivate(fakeself) {
    if (fakeself.header() == "Article 2") { fakeself.blah("I blow") };
}
var acdvm = function (args) {
    var self = this;
    self.blah = ko.observable('blah');
    self.activate = function () {
        externalActivate(self);
        if(self.header()=="Article 5") {self.blah("Really Sucks")};
    };
... rest unchanged
}
return acdvm;

并更改视图以在我实例化的6个视图中的每个视图上显示blah。在我的主视图模型中我添加了:

    acd3.blah("sucks");

转到模块的"activate"方法,所有的工作都完全按照预期进行。

在屏幕上的6列中,我得到了"blah","I blow","sucks","blah","Really sucks","blah",这正是我需要的。然而,如果我在第一列/视图模型上使用输入字段来选择一些东西,那么一旦视图模型加载数据并改变可观察对象,触发该视图中的html被"填充",那么它出现在第六列,而不是第一列!

这太疯狂了…我真的不知道这是怎么发生的

更多信息而不是答案

根据组合文档,如果你传递一个模块ID给组合绑定,它将"定位模块,定位它的视图,绑定它们并将它们注入DOM。"。当传递一个对象实例时,它会"定位它的视图,绑定它并将其注入DOM"。也许这里有细微的区别?我对Durandal的内部不太熟悉。

另一个想法是,不要绑定到主视图模型的属性,你可以尝试这样做:

<div class="container acd">
    <div class="row">
        <div class="col-md-2">
            <div data-bind="compose: 'viewmodels/articleComparisonDetail', activationData: { header: 'Article1' }"></div>
        </div>
        <div class="col-md-2">
            <div data-bind="compose: 'viewmodels/articleComparisonDetail', activationData: { header: 'Article2' }"></div>
        </div>
        <div class="col-md-2">
            <div data-bind="compose: 'viewmodels/articleComparisonDetail', activationData: { header: 'Article3' }"></div>
        </div>
        <div class="col-md-2">
            <div data-bind="compose: 'viewmodels/articleComparisonDetail', activationData: { header: 'Article4' }"></div>
        </div>
        <div class="col-md-2">
            <div data-bind="compose: 'viewmodels/articleComparisonDetail', activationData: { header: 'Article5' }"></div>
        </div>
        <div class="col-md-2">
            <div data-bind="compose: 'viewmodels/articleComparisonDetail', activationData: { header: 'Article6' }"></div>
        </div>
    </div>
 </div>

请记住,您将不得不重构您的articleComparisonDetail视图模型:

 var vm = {
    var self = this;
    self.header = ko.observable();
    self.activate = function (data) {
        self.header(data.header); // or whatever
    }
    // rest of code...
 }
 return vm;

结果证明我所做的一切都很好,除了……

我在"detail"视图模型中嵌入了一个自定义绑定处理程序(我没有在上面的代码中包含它,因为我认为它不相关-我错了)。

我所做的就是首先将bindinghandler移到视图模型之外,然后我在bindinghandler初始化(这是视图模型)上添加了第4个参数,以便它知道虚拟机的哪个实例调用了它。

在bindinghandler中,我调用填充可观察对象并显示一个图表,我只是引用了"vm"参数,我现在在初始化时包含而不是"self"。然后,一切又变得美好起来。

所以看起来我已经正确地设置了我的视图/模型(正如我从测试中怀疑的那样),而这只是自定义绑定处理程序中不正确的"self"。

感谢输入的章节,是有用的阅读

最新更新