我有一个小的,简单的视图&显示一些数字和图表的视图模型。我被要求提供一个"并排"视图,这样最多可以并排显示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"。
感谢输入的章节,是有用的阅读