将jQuery动态树与Knockout和Breeze一起使用

Using jQuery dynatree with Knockout and Breeze

本文关键字:Breeze 一起 Knockout jQuery 动态      更新时间:2023-09-26

好的,根据PW Kad的建议,我将从问题ID 17973991开始的地方拆分这部分问题。

我有一个视图模型,它利用了围绕微风构建的数据上下文,它获取了我想要的数据,并填充了可观察的数组。我需要使用Breeze已经检索到的数据来填充另一个(可观察的)数组,以便在树视图中使用。

由于现有数据没有正确的字段名,我需要能够创建一个具有正确字段名的新数组,供dynatree/fancytree插件使用。

我的第一次尝试:(随后显示不起作用,所以不要这样做!)

因此,在我的视图模型中,我在.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"部分

最后将"激活"方法改为使用新方法:

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,但我在可观察的材料中有"materialName",因此通过对可观察材料进行切片来创建阵列上的"$.each",以将"materialName"属性推送到我的新阵列(tmpArray)中的"name"属性中。我对这一切都是新手,我可能离目标很远!

我真的需要一个可观测的数组吗。。。?如果我了解可观测阵列的用途,我想我不会这么做。。。我的材料几乎是一成不变的,很少会改变。我想我可以简单地将"treeMaterials"作为一个标准的javascribt对象数组,并在视图模型中返回它,而不是将其作为一个observableArray?

无论哪种方式,目前materialname和ID的值都没有传递到我正在制作的tmpArray中的相关属性中。相反,我从可观察的材料中获得函数,所以我认为我需要用某种"打开包装"来获得实际值?

您没有填充treeMaterials,因为当您将其发送到asTreeMaterials时,材料中没有任何数据。我在这里做了一些假设,但基本上看起来这就是你想要做的——

在视图模型的顶部,我假设您有两个可观测阵列

var treeMaterials = ko.observableArray();
var materials = ko.observableArray();

对于activate方法,您需要获取一些数据,然后当您的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是如何处理可观测对象的,所以这里有一个标准的不可观测对象数组,而不是一个可观测数组-

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));
    });
};