好的,按照PW Kad的建议,我将问题的这一部分从问题ID 17973991开始的地方分开。
我有一个viewmodel,它利用围绕微风建立的datacontext,并获取我想要的数据并填充可观察数组。我需要使用Breeze已经检索的数据来填充另一个(可观察的)数组以在树视图中使用。
由于现有数据没有正确的字段名,我需要能够使用dynatree / fancytree插件可以使用的正确字段名创建一个新数组。
我的第一次尝试:(后来显示不起作用,所以不要这样做!)
所以在我的viewmodel中,我在.js文件的顶部添加了以下内容:
var treeMaterials = ko.observableArray();
var treeMaterial = function (data) {
var self = this;
self.name = ko.observable(data.name);
self.id = ko.observable(data.id);
self.children = ko.observableArray();
$.each(data.children, function (index, item) {
self.children.push(new Person(item));
});
};
然后我在我的模块中添加了“asTreeMaterials”方法:
var asTreeMaterials = function (treeMatsObservable, matsObservable) {
treeMatsObservable([]); //clear out array as we're rebuilding it in here
var tmpArray = treeMatsObservable(); //create local temp array to avoid ko notifications on each push
$.each(matsObservable, function (index, mat) {
tmpArray.push(new treeMaterial({
id: mat.id,
name: mat.materialName,
children: []
}));
});
treeMatsObservable(tmpArray);
};
(大量借用John Papa的编码,感谢John!) 注意:一旦我掌握了基础知识,就会有更多代码进入“children”位。
最后更改“activate”方法以使用新方法:
var activate = function () {
// go get local data, if we have it
return datacontext.getMaterialPartials(materials),
asTreeMaterials(treeMaterials, materials);
};
....
然后从模块返回新数组:
var vm = {
activate: activate,
materials: materials,
treeMaterials: treeMaterials,
title: 'My test app page 1',
refresh: refresh
};
表示我没有再次访问服务器以获取数据的树视图版本。
编辑2。 根据PW Kad关于另一个问题的指导(将很快添加到这个问题)我修改了“asTreeMaterials”方法如下:
var asTreeMaterials = function () {
treeMaterials([]); //clear out array as we're rebuilding it in here
var matArray = materials().slice();
var tmpArray = [];
$.each(matArray, function (index, mat) {
tmpArray.push(new treeMaterial({
id: mat.id,
name: mat.materialName,
children: []
}));
});
treeMaterials(tmpArray);
};
原因(我认为)我必须创建一个单独的新数组,即我切片的现有“材料”可观察不包含正确的属性。 Dynatree / fancytree需要(除其他外)“ID”和“名称”。我有ID,但我在材料observable中有“materialName”,因此通过切片可观察的材料创建的数组上的“$ .each”将“materialname”属性推送到我的新数组中的“name”属性(tmpArray)。我对这一切都很陌生,我可能会在这里走得更远!
我真的需要一个可观察的阵列......?如果我理解可观察阵列的用途,我认为我不会这样做......我的材料几乎是一成不变的,而且很少会发生变化。我认为我可以简单地将“treeMaterials”作为标准的javascribt对象数组并在viewmodel中返回它而不是使它成为observableArray?
无论哪种方式,目前materialname和ID的值都不会传递到我正在制作的tmpArray中的相关属性中。相反,我从材料中可以观察到函数,所以我认为我需要通过某种“解包”来获得实际值?
答案 0 :(得分:0)
您没有填充treeMaterials,因为当您将其发送到asTreeMaterials时,材料中没有任何数据。我在这里做了一些假设,但基本上看起来这就是你想要做的事情 -
在视图模型的顶部,我假设您有两个observableArrays
var treeMaterials = ko.observableArray();
var materials = ko.observableArray();
对于你的激活方法,你需要获取一些数据,然后当你的datacontext返回一个promise时,从一些对象类型中创建一个树 -
var activate = function () {
return datacontext.getMaterialPartials(materials).then(
makeMyTree);
};
您不需要传递treeMaterials或材料,因为它们已经在视图模型的范围内,并且您只是想从材质中创建一个对象树。
var makeMyTree = function () {
treeMaterials([]);
ko.utils.arrayForEach(materials(), function (mat) {
treeMaterials.push(new treeMaterial(mat));
});
};
这将创建一个具有可观察属性的observableArray对象,这意味着如果你传递它们或试图获取它们的值,你需要使用像treeMaterials()[0] .name()这样的东西。
如果您的dynatree没有观察到,或者与他们玩得不好
我不确定你的dynatree或w / e如何与observable一起使用,所以这里是一个标准的非可观察对象数组而不是一个可观察数组 -
var treeMaterials = [];
var makeMyTree = function () {
treeMaterials[];
ko.utils.arrayForEach(materials(), function (mat) {
treeMaterials.push(new treeMaterial(mat));
});
};
var treeMaterial = function (data) {
var self = this;
self.name = data.name;
self.id = data.id;
self.children = [];
$.each(data.children, function (index, item) {
self.children.push(new Person(item));
});
};