2016-05-27 15 views
0

ノックアウトを発見するだけで、ここで何かを逃したら愚かさを指摘してください。私は現在、ノックアウトで観測可能なものに複数選択されています。Knockout.js複数選択と区切り文字列の間の双方向バインディング

<select class="form-control" id="SithSelect" data-bind="attr: { 'data-has-value': (Sith() ? true : false) }, selectedOptions: Sith() ? Sith().split('|') : '' " placeholder="The dark side" multiple> 
    <option disabled></option> 
    <option value="Darth Vader">Darth Vader</option> 
    <option value="Darth Maul">Darth Maul</option> 
    <option value="Darth Bane">Darth Bane</option> 
</select> 

ここで、 "Sith"は観測可能な文字列値です。

データベースに「Darth Vader | Darth Maul」という文字列値を手動で追加すると、最終的に値がクライアント側に下がり、複数選択で正しく選択された2つの値が表示されます。

ただし、値を変更すると、選択した値をオブザーバブルに保存されたパイプ区切り文字列に戻す方法はありますか。

私が試したことから、selectにバインドされた観測可能な配列を持つことでこれをソートし、データベースに保存する際にパイプで区切られた文字列を再構成することができます。このソリューションでは、個々のselect要素(これはDBのパイプ区切り文字列を使用するページ上の唯一の要素)と密接に関連しているため、コードを見て少し面白いです。

複数の選択文字列と区切られた文字列の間で双方向バインドを行うことに何か不足していますか?代わりに、複数の選択されたオプションをバインディングの観測可能な値に戻して割り当てるときに、逆の処理をする方法がありますか?

UPDATE:質問がに絞られました:

私は書くことができるように、計算値の読み取り/書き込み機能を処理することができ、私はバインディングの中に置くことができることをノックアウトする作り付けの何かが、あります独立して計算された観測可能な値を作成する必要はなく、インライン化されていますか?

+0

あなたはこれが間違った方法に近づいていると思います。選択されたオプションは、viewModleに設定された観測可能な配列でなければなりません – brianlmerritt

+0

はい、上記のように、観測可能な配列にバインドしてパイプの区切り文字列を再構築することはできましたが、残りのバインディングがどのように一般的であるかと比べて – DarthJam

答えて

1

selectedOptionsは、配列または観測可能な配列でなければなりません。 http://knockoutjs.com/documentation/selectedOptions-binding.html

Sithから計算されたデータを渡すときに、ノックアウトがSithにデータを保存する方法を知る方法はありません。

ko.observableArrayまたは配列値のko.observableを使用する必要があります。しかし、文字列の値と配列の値を同期させる必要があります。代わりに、手動で(http://knockoutjs.com/documentation/computed-writable.html)書き込み可能な、計算を使用することができます(STR =>編曲、編曲=>文字列)2つのサブスクリプションをサポートする:

<select data-bind="selectedOptions: sith">...</select> 
vm.sithString = ko.observable(''); 
vm.sith = ko.computed({ 
    read: function() { return vm.sithString().split('|'); }, 
    write: function(arr) { vm.sithString(arr.join('|')); } 
}); 

UPDATE

を何かがあります私はバインド内に置くことができ、計算された値の読み込み/書き込み関数を扱うことができるので、別の計算された観測可能な値を作成するのではなく、インラインで書くことができます。

これはMVVMのViewModelの正確な目的です。あなたは純粋なデータであるモデルを持っています(まあ、それは観測可能なものに保存しなければなりませんが、とにかく)。純粋にUIのものであるバインディングがあります。また、それらの間でデータとイベントを変換するViewModel間のメディエータがあります。この例では、WritableはViewModel-Modelリレーションを表しています。

書き込み可能な計算は、バインディングごとにwrite/read関数よりはるかに一般的かつ柔軟なメカニズムです。

UPDATE 2 まあ、selectedOptionsはの上に座って結合が最も簡単ではありません。方法は、正確に同じ計算された要素を添付し、バインディング関数でvalueAccessorを置き換えることです。コードは単純ですが、うんざりの仕組みに関する知識が必要です。

var selectedOptions = ko.bindingHandlers['selectedOptions']; 
ko.bindingHandlers['pipedOptions'] = { 
    after: selectedOptions.after, /* ['options', 'foreach'] */ 
    init: function(el, va) { 
    var obsv = va(); 

    var mediator = ko.computed({ 
     read: function() { return obsv().split('|'); }, 
     write: function(arr) { obsv(arr.join('|')); } 
    }); 

    ko.utils.domData.set(el, 'pipedOptions.mediator', mediator); 

    var args = [].slice.call(arguments); 
    args[1] = function() { return mediator; }; 
    selectedOptions.init.apply(this, args); 
    }, 
    update: function(el, va) { 
    var mediator = ko.utils.domData.get(el, 'pipedOptions.mediator'); 
    var args = [].slice.call(arguments); 
    args[1] = function() { return mediator; }; 
    selectedOptions.update.apply(this, args); 
    } 
}; 

もっと複雑な動作が必要な場合は、コンポーネントを見てください。

+0

はい私は同様のものを思い付いたが、それはずっときれいだね、ありがとう。私は私の質問がもっとあったと思う、私はバインディング内に配置することができます、私はインラインで書くことができるように、計算された値の読み取り/書き込み関数を処理することができますノックアウトに何かがあります観察可能な価値? 私は質問を更新します – DarthJam

+0

カスタムバインディングは進歩していると思います - 私はさらに読むことをしています – DarthJam

+0

@LordJamなぜカスタムバインディングが必要でしょうか?標準のオプションはあなたが望むものです: '