select
要素に対する次の ko バインディングを検討してください。
<select data-bind="value: valueObservable, options: optionsObservableArray,
optionsCaption: '[None] - this is an optional field'">
...次のようなビューモデルが与えられます:
function MyViewModel()
{
var self = this;
self.valueObservable = ko.observable();
self.optionsObservableArray = ko.observableArray();
// ajax call to load options
ko.computed(function() {
$.ajax(...)
.success(function(optionsResponse) {
self.optionsObservableArray(optionsResponse)
});
});
// ajax call to load data value
ko.computed(function() {
$.ajax(...)
.success(function(valueResponse) {
self.valueObservable(valueResponse)
});
});
}
これについて奇妙なのは、2 番目の (データ) ajax 呼び出しが最初の (オプション) ajax 呼び出しの前に返される場合です。select
要素にはバインディングがあるため、これoptionsCaption
が起こっていると私が信じていることです:
- データ ajax 呼び出しが完了し、
valueObservable
何らかの値 (6、abc、またはその他の偽でない値など) が設定されます。 option
要素には 1 つしかなくselect
( によりoptionsCaption
)、valueObservable
が (バインディングを介してvalue
) バインドされているため、これにより がvalueObservable
に変更されundefined
ます。- 最後に、は に新しい要素を
optionsObservableArray
完成させて追加しますが、この時点では手遅れです。 は、最初の ajax 呼び出しから返された実際のデータ値ではなく、値をラップしています。option
select
valueObservable
undefined
質問: これを回避する最善の方法は何ですか? これが私が考えることができるものです:
- で最初の ajax 呼び出しを実行し
async: false
ます。これにより、ページのレンダリングが遅くなる場合があります。 - 選択値 ( など
value: selectedValueObservable
) にバインドするための別のオブザーバブルを作成します。次に、 にサブスクライブし、optionsObservableArray
そのサブスクリプションを使用して のようなことを行いますself.selectedValueObservable(self.valueObservable())
。これは応急処置のようです。 - サーバーからオプション データを送信することにより、javascript が実行される前に、選択とオプションをページにレンダリングします (MVC ビューモデルを使用)。これにより、オプションを として扱うのが少し難しくなります
observableArray
。
アップデート
サンプルコードを単純化するために、この質問から省略した別の懸念があります。実際には、このビューモデルはデータ項目の編集可能なリストを作成するために使用されます。そのため、実際には、ページにレンダリングされるドロップダウン リストが複数あります。データ ajax 呼び出しは実際には配列を返し、その成功関数は実際にobservableArray
は複雑な項目の を設定します。ドロップダウン リスト オプションはすべてのインライン フォームで再利用されるため、$parent
viewmodel に配置され、一度だけ読み込まれます。また、データ項目は WebAPI を介して取得されるため、単一の ajax 呼び出しで選択オプションを渡すことも困難です (IEnumerable
追加のドロップダウン オプションを送信する余地がありません)。