我有一个小而简单的视图&显示某些数字和图表的viewmodel。我被要求提供一个“并排”的视图,其中最多可以并排显示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>
,这在viewmodel中:
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'});
...其中“acd”是我的viewmodel中的“required”引用链接到独立视图&amp;视图模型。
这似乎首先起作用,我在页面上并排有6个实例,上面设置了不同的标题。
然而,当我开始实际触发一些加载事件,其中一个部分是数据绑定到一个控制它是否可见的observable时,似乎没有足够的实例分离,因为在第一个实例中更改了一个下拉列表实际上揭示了第6节中的部分!
当我通过chrome dev工具检查页面上的元素时,所有的div ID是相同的,所以我想我在这里尝试实现的是一个根本问题?我认为通过在母版页中创建“新”实例,它将创建自我感知的独立实例,以便在传递参数/更新时,他们会知道引用自己的ID实例,但它看起来不会。
有人有任何指示试着帮助我吗?
主页面viewmodel:
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个单独的值。不知何故,虽然各个细节视图中的输入框似乎与特定实例没有关联。
acd“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>
...和viewmodel(也简化)
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");
到模块的“激活”方法,所有这些都完全符合预期。
在屏幕上的6栏中,我得到了“等等”,“我吹”,“糟透了”,“等等”,“真的很糟糕”,“等等”,这就是我所需要的。然而,如果我使用第一列/ viewmodel上的输入字段来选择某些内容,那么只要viewmodel加载数据并更改了observable,触发该视图中的html“填入”然后它就出现在第6列中,不是第一个!
这太疯狂......我真的不知道这是怎么回事。
答案 0 :(得分:0)
更多信息而不是答案。
根据Composition文档,如果您将模块ID传递给撰写绑定,它将&#34;找到模块,找到它的视图,绑定它们并将它们注入到DOM中。 #34; 。传递对象实例时,它将&#34;找到它的视图,绑定它并将它们注入到DOM中。&#34; 。也许这里有微妙的区别?我对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;
答案 1 :(得分:0)
事实证明,除了......之外,我所做的一切都很好。
我嵌入在&#34;详细信息中的自定义绑定处理程序&#34; viewmodel(我没有在上面的代码中包含这个,因为我认为它不相关 - 我有多么错误。)
我所做的一切就是首先将绑定处理程序移到viewmodel之外,然后我在bindinghandler初始化(这是viewmodel)上添加了第4个参数,以便它知道vm的哪个实例已经调用它。
在我打电话来填充可观察量并显示图表的绑定处理程序中,我刚刚提到了&#34; vm&#34; param我现在包括在初始化而不是&#34; self.whatever&#34;和宾果游戏,一切都再次变得很好。
所以我似乎正确地设置了我的观点/模型(正如我在测试中所怀疑的那样)并且它只是一个不正确的&#34;自我&#34;在作为罪魁祸首的自定义绑定处理程序中。
感谢输入的破解,很有用。