Bootstrapでいろいろやると結局DOM操作になる…
Modalに宛てるViewModelを定義しても、表示するのは結局jQueryを使っていたりしてどうにも趣味じゃなかったので、多少見た目がよくなるようにと思ってカスタムバインディングを作ってみました。
ハンドラーを定義する
モーダルは閉じる用のボタンを押したりしなくても閉じることがあるので、万が一ViewModelを通じて表示・非表示の操作が行われた場合のことも考慮して、表示・非表示のコールバックイベントを使って状態を変更する処理も定義しておきます。
CoffeeScript
ko.bindingHandlers.bs_modal = {
init: (element, valueAccessor) ->
# モーダルの表示・非表示の際に状態を変化させる
$(element).on 'shown.bs.modal', ->
value = valueAccessor()
value(true) unless value()
$(element).on 'hidden.bs.modal', ->
value = valueAccessor()
value(false) if value()
ko.computed(
read: ->
state = ko.unwrap(valueAccessor())
if (state)
$(element).modal('show')
else
$(element).modal('hide')
,
disposeWhenNodeIsRemoved: element
)
}
実際に使ってみる。
View(モーダルのHTML)
data-bindする際に、bs_modalにbool型のobservableを指定します。
slim
button#btn_show_modal
.modal.fade role="dialog" data-bind="bs_modal: state"
.modal-dialog
.modal-content
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title モーダルタイトル
.modal-body
p モーダルボディ
.modal-footer
.container-fuild
.row
.col-md-offset-6.col-md-3
button.btn.btn-danger.btn-block type="button" data-dismiss="modal"
| キャンセル
.col-md-3
button.btn.btn-default.btn-block type="button"
| ボタン
ViewModel
次は、ViewModelのです。
指定したobservableの値が変われば、モーダルの表示・非表示ができるので、
それ用のメソッドを定義しておきます。
CoffeeScript
class @ModalViewModel
constructor: ->
@state = ko.observable(false)
show: ->
@state(true)
hide: ->
@state(false)
$ ->
vm = new ModalViewModel()
ko.applyBindings(vm)
# モーダルを表示するイベントを設定してみる。
$('#btn_show_modal').click ->
vm.show()
感想
ViewModelに対して表示・非表示の切り替えの命令ができるので、すっきりしました。