3

私は、会社によって提供される可能性のある観察可能な一連のサービスを持っています (つまり、セールス、サービス、コンサルティング)。これらの各サービスは、米国のゼロ以上の州で会社によって実施される場合があり、各州にはオプションの認証番号があります。したがって、サービスには監視可能な場所の配列があり、場所は州と証明書番号の組み合わせです。

function Service(name) {
    var self = this;

    self.Name = ko.observable(name);
    self.Locations = ko.observableArray();
}

function Location(state) {
    var self = this;

    self.State = ko.observable(state);
    self.CertNum = ko.observable();
}

ユーザー インターフェイスで、米国のすべての州の 1 つのリストを表示したいと考えています。ユーザーは、会社が運営されている各州の横にあるチェックボックスをオンにして、州の「マスター リスト」を作成します。このマスター リストは、可能なサービスのそれぞれの下に表示される選択肢を決定します。

たとえば、ユーザーはマスター リストで「アラバマ」と「アリゾナ」にチェックを入れます。次に、UI は、チェックボックスとテキストボックスの組み合わせとして、サービスごとに個別の場所をレンダリングします。マスター ビュー モデルは次のとおりです。

function viewModel() {
    var self = this;

    self.AllStates = [
        { name: "Alabama", abbrev: "AL" },
        { name: "Alaska", abbrev: "AK" },
        { name: "Arizona", abbrev: "AZ" },
        { name: "Arkansas", abbrev: "AR" }
    ];

    self.BusinessStates = ko.observableArray();

    self.AllSelectedStates = ko.computed( function() {
        return ko.utils.arrayFilter( self.AllStates, function(item) {
            return self.BusinessStates.indexOf(item.abbrev) >= 0;
        });
    });

    self.Services = ko.observableArray([
        new Service("Sales"),
        new Service("Service"),
        new Service("Consulting")
    ]);
}

単純なビューは次のようになります。

<h2>Master List</h2>
<ul data-bind="foreach: AllStates">
    <li>
        <label><input type="checkbox" data-bind="value: abbrev, checked: $root.BusinessStates"/> <span data-bind="text: name"></span></label></li>
</ul>

<h2>Services</h2>
<div class="service" data-bind="foreach: Services">
    <h3 data-bind="text: Name"></h3>
    <ul data-bind="foreach: $root.AllSelectedStates">
        <li>
           <label>
             <input type="checkbox" data-bind="value: abbrev, checked: $parent.Locations" /> 
             <span data-bind="text: name"></span>
           </label> 
           <input type="text" placeholder="Cert. Number" data-bind="value: ??" />
        </li>
    </ul>
</div>

そのビューは、少なくとも Service の Locations 配列に入力された状態を取得しますが、CertNum プロパティをバインドする方法がわかりません。

ユーザーがマスター リストで Alabama と Arizona を選択したとします。ここで、「Sales」サービスの場合、ユーザーは「Arizona」にチェックマークを付け、認証番号「98765」を入力します。「コンサルティング」サービスの下で、ユーザーは「アラバマ」にチェックマークを付け、証明書番号を入力しません。理想的には、結果の JSON スニペットが次のようになることを望みます。

"Services": [
    {
        "Name": "Sales",
        "Locations": [
            {
                "State": { "name": "Arizona", "abbrev": "AZ" },
                "CertNum": "98765"
            }
        ]
    },
    {
        "Name": "Service",
        "Locations": []
    },
    {
        "Name": "Consulting",
        "Locations": [
            {
                "State": { "name": "Alabama", "abbrev": "AL" },
                "CertNum": null
            }
        ]
    }
]

米国の州の「マスター リスト」をレンダリングしてバインドできます。サービスを繰り返し処理し、利用可能なサービスの場所ごとにコントロールを提供する UI をレンダリングできます (つまり、状態のチェックボックス、証明書番号のテキストボックス)。私ができなかったのは、サービス ロケーション コントロールをバインドして、適切な Locations 配列内のロケーションのメンバーシップを制御し、同時に認証番号の値に影響を与えることです。

私が行った最も近い試みはかなり複雑でハックです。knockout-postBox プラグインを使用して、viewModel.AllSelectedStates プロパティを各 Service モデルの同様のプロパティにリンクし、新しい Locations を各 Service.Locations 配列にプッシュします。 . マスターリストで状態がチェックまたはチェック解除されるたびに、サービスへの変更を消去することを除いて、ほとんど機能しますまた、利用可能なすべての場所を各サービスの Locations 配列にプッシュし、その場所が選択されているかどうかを判断するために、その場所の IsSelected ブール値フラグに依存する必要があります (選択された場所だけを配列に入れたいと思います)。

この JSFiddle で試行を確認できます: http://jsfiddle.net/cbono/PU6Sq/23/

これの良いところは、UI がどのように動作するかを示していることです。しかし、これは postBox プラグインがなくても可能だと思います。答えを導き出す正しい方法で問題を見ていないだけです。私はこれに数日を費やしましたが、100% 機能するソリューションを思いつくことはできません。

4

1 に答える 1

0

visibleコレクション イベントを管理するよりも、バインディングを使用する方が簡単です。

<li data-bind="visible: State().IsSelected">

http://jsfiddle.net/MizardX/XTkpb/


それらを本当に処理する必要がある場合は、StateAndCertオブジェクトをオブジェクトにキャッシュできServicesます。

var self = this,
    cache = {};

self.Locations = ko.computed(function () {
    return ko.utils.arrayMap(states(), function (item) {
        var key = item.Abbrev();
        if (cache[key] === undefined) {
            cache[key] = new StateAndCert(item);
        }
        return cache[key];
    });
});

http://jsfiddle.net/MizardX/HMatE/


function(){}JSON レンダリングから特定のプロパティを非表示にするには、プロパティ内にそれらを詰め込むことができます。

self.Meta = function(){};
self.Meta.IsSelected = ko.observable(false);
于 2012-12-18T08:33:55.640 に答える