ものすごくハマったので、メモ。
Knockout.jsでselectを作るのはお手軽で、デフォルト値を設定するのもvalueを使うだけでいいのですが、Ajaxで取得したJSONを使ってフォームを更新しようとしたところ、デフォルトの値が設定されなくて困りました。
Before
まずはView
#new_foo data-bar_id="1"
select.select.form-control(
name="foo[bar_id]"
data-bind="options: bars, optionsText: 'name', optionsValue: 'id', optionsCaption: '選択してください', value: default_bar_id")
そしてViewModel
class window.BarViewModel
constructor: (bar_id)->
@bars = ko.observableArray()
@default_bar_id = ko.obserbable(bar_id)
$ ->
# selectのデフォルト値になる値を取得
bar_id = $('#new_foo').data('id')
# bindingしておく
bar_vm = new BarViewModel(bar_id)
ko.applyBindings(bar_vm)
# selectのoption用のデータを取得
$.getJSON '/bars.json', (data) ->
bar_vm.bars(data)
これで、selectのデフォルトがbar_idの値の項目になるであろう…と思ったらなりませんでした。おそらく、すでに一度data-bindの中を評価した後なので、optionsの内容が変わってからまたvalueを評価してもおかしなことになるからでしょう。
After
これを解決するには、if文を使って表示・非表示を設定します。
#new_foo data-bar_id="1"
/! ko if: bars().length > 0
select.select.form-control(
name="foo[bar_id]"
data-bind="options: bars, optionsText: 'name', optionsValue: 'id', optionsCaption: '選択してください', value: default_bar_id"
)
/! /ko
if文で要素の表示・非表示を設定すると、非表示の際には要素自体がなくなります。そのため、trueになった際には、要素が再構成されるため、data-bindの設定が再評価されるのだと思います。
Ajaxでselectの内容を変更する際には、気をつけましょう!
参考URL