0

サーバーから JSON として受信した sku 識別子を持つ製品オプションのリストがあります。次に、選択されている前提条件の値に依存する他のオプションがあります。これはrequires、製品オプション配列の配列プロパティによって定義されます。

var serverOptions = [{
    name: "DELL R210",
    price: 100,
    sku: 1001,
},{
    name: "DELL R710",
    price: 200,
    sku: 1002,
},{
    name: "DELL R720 Dual CPU",
    price: 300,
    sku: 1003,
}];

var osOptions = [{
    name: "Windows Standard",
    sku: "201",
    price: 1,
}, {
    name: "Windows Enterprise",
    sku: "202",
    price: 2,
}, {
    name: "CentOS",
    sku: "203",
    price: 0,
}, {
    name: "Debian",
    sku: "204",
    price: 4,
}];

var databaseOptions = [{
    name: "None",
    sku: "0",
    price: 0,
}, {
    name: "SQL Express",
    sku: "401",
    requires: ["201", "202"],
    price: 10,
}, {
    name: "SQL Standard",
    sku: "402",
    requires: ["202"],
    price: 5,
}, {
    name: "MySQL",
    sku: "MySQL1",
    requires: ["201", "202", "203"],
    price: 11,
}, {
    name: "RavenDb",
    sku: "403",
    requires: ["203"],
    price: 12,
}, {
    name: "MongoDB",
    sku: "404",
    requires: ["204"],
    price: 13,
}];

var clusterOptions = [{
    name: "None",
    sku: "0",
    price: 0,
}, {
    name: "Standard MySQL Cluster",
    sku: "4101",
    requires: ["MySQL1"],
    price: 10,
}, {
    name: "Enterprise MS SQL Cluster",
    sku: "4102",
    requires: ["402"],
    price: 5,
}, {
    name: "NoSQL Sharding",
    sku: "4103",
    requires: ["403","404"],
    price: 10,
}];

私のビューモデルでは、次のコードを使用して選択可能な値をフィルター処理します (ほとんどの場合一般的であり、チェックが必要なクエリに使用されているものに応じて変数参照が変わります)。

self.availableClusteringOptions = ko.computed(function () {
        var selectedDbSku = this.selectedDb();

        if (typeof selectedDbSku === "undefined")
            return [];

        return ko.utils.arrayFilter(this.dbClusteringOptions, function (dbCluster) {
            if (typeof dbCluster.requires === "undefined")
                return true;
            else
                return dbCluster.requires && dbCluster.requires.indexOf(selectedDbSku) > -1;
        }, this);
    }, this);

私のコードは機能しますが、事前に手動で静的に入力されます。新しいフィールドを追加すると、コードの構文が同じであるため、変数が変更されるだけで多くのコピーペーストが行われます(ポイントの場合self.availableDatabasesself.availableClusteringOptions)。

将来的には、(サーバー データベースから) 完全に新しいオプション オブジェクトを追加する可能性があります。このオプション オブジェクトは、すべて動的に処理、マッピング、および関係を作成する必要があります。追加される可能性のある将来の製品オプションは、たとえば次のようになります。

var managementOptions = [{
    name: "Self managed",
    sku: "0",
    price: "0"
},{
    name: "Windows Management",
    sku: "WindowsManagement",
    price: 1,
    requires: ["201", "202"],
}, {
    name: "Linux Management",
    sku: "LinxManagement",
    requires: ["203", "204"],
    price: 2,
}, {
    name: "Basic Management",
    sku: "ManageAll",
    price: 0,
    requires: ["201", "202","203","204"],
}]; 

特にこのデータはデータベースから供給されるため、これは自動化を求めていますが、どこから始めればよいかわかりません。

json からビューモデルを作成するノックアウト マッピング プラグインを見たことがありますが、ドキュメントからは、JSON が例よりもはるかに複雑であるため、これがデータ構造とどのように結びつくのかわかりません。

このコードを自動化して、追加の依存する「要件」の前提条件値を動的に設定できるようにするにはどうすればよいですか? この場合、ノックアウト マッピングは役に立ちますか、それとも代替手段を検討する必要がありますか?

フィドルはこちら: http://jsfiddle.net/g18c/E54YC/7/

var serverConfig = function () {
    var self = this;

    self.osOptions = osOptions;
    self.dbOptions = databaseOptions;
    self.dbClusteringOptions = clusterOptions;
    self.serverOptions = serverOptions;

    self.selectedServer = ko.observable();
    self.selectedOs = ko.observable();
    self.selectedDb = ko.observable();
    self.selectedDbCluster = ko.observable();

    self.lookupItemForSku = function (lookup, values) {
        if ((typeof lookup != "undefined") && (lookup != "0"))
            return ko.utils.arrayFirst(values, function (item) { return item.sku == lookup; }, this);
        else
            return null;
    };

    self.availableDatabases = ko.computed(function () {
        var selectedOsSku = this.selectedOs();

        if (typeof selectedOsSku === "undefined")
            return [];

        return ko.utils.arrayFilter(this.dbOptions, function (db) {
            if (typeof db.requires === "undefined")
                return true;
            else
                return db.requires && db.requires.indexOf(selectedOsSku) > -1;
        }, this);
    }, this);

    self.availableClusteringOptions = ko.computed(function () {
        var selectedDbSku = this.selectedDb();

        if (typeof selectedDbSku === "undefined")
            return [];

        return ko.utils.arrayFilter(this.dbClusteringOptions, function (dbCluster) {
            if (typeof dbCluster.requires === "undefined")
                return true;
            else
                return dbCluster.requires && dbCluster.requires.indexOf(selectedDbSku) > -1;
        }, this);
    }, this);

    self.availableDatabases.subscribe(function () {
        self.selectedDb(self.availableDatabases()[0].sku);
    });

    self.availableClusteringOptions.subscribe(function () {
        self.selectedDbCluster(self.availableClusteringOptions()[0].sku);
    });

    self.selectedServer(self.serverOptions[0].sku);
    self.selectedOs(self.osOptions[0].sku);

    return self;
};

var configModel = new serverConfig();

ko.applyBindings(configModel);
4

1 に答える 1

1

これは、データをマップする独自のモデルを作成する方法を示すフィドルの簡単な更新です - http://jsfiddle.net/E54YC/9/

より熱心になり、関係マッピングを行いたい場合は、多くの選択肢がありますが、上位 2 つを検討します。

  1. 要件を処理する独自のカスタム コードを記述し、その要件に応じてこれまたはそれを選択できるかどうか

  2. クライアント側のデータ ライブラリ (ORM) を使用して、リレーションシップ マッピングが処理される Breeze.js のように処理します。ビュー モデルにロジックを配置するだけで済みます。

モデルの例 -

function serverModel (server) {
    var self = this;
    self.Name = ko.observable(server.name);
    self.Price = ko.observable(server.price);
    self.SKU = ko.observable(server.sku);
}
于 2013-10-17T19:01:46.970 に答える