js から Bootstrap の Modal を表示してそのモーダル上での操作に応じてなにかしたいとき(典型的には確認ダイアログとか)、Modal を Promise として扱えるようにしておくと async/await で直列に書けて便利です。
const promisifyModal = (modal, param) =>{ const $modal = $(modal); return new Promise((resolve) => { $modal .data('modal-param', param) .data('modal-result', null) .off('hidden.bs.modal') .one('hidden.bs.modal', () => { resolve($modal.data('modal-result')); $modal .data('modal-param', null) .data('modal-result', null) }) .modal('show') }); };
モーダルを開く側は次のように await でモーダルが閉じるのを待ってその結果を得ることが出来ます。
$('#show-modal').on('click', async (ev) => { console.log('モーダルを表示します'); try { // モーダルにわたすパラメータ const param = 'ほげほげ'; // モーダルを表示して閉じるまで待つ const result = await promisifyModal('#modal', param); if (result != null) { // モーダルの結果でなにかする console.log(`モーダルの結果は ${result} です`); } } finally { // モーダルが閉じた後 console.log('モーダルが閉じました'); } });
表示されるモーダルの側は次のような HTML と js です。モーダルの表示時は $modal.data('modal-param')
でモーダルを開く側から渡されたパラメータが受け取れて、モーダルの結果は $modal.data('modal-result')
に入れています。
<div class="modal fade" id="modal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">モーダル</h5> <button type="button" class="close" data-dismiss="modal"> <span>×</span> </button> </div> <div class="modal-body"> <input type="text"> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" data-modal-ok>OK</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">キャンセル</button> </div> </div> </div> </div>
const $modal = $('#modal'); $modal.on('show.bs.modal', (ev) => { // モーダルに渡されたパラメータでなにかする const param = $modal.data('modal-param'); $modal.find('input[type="text"]').val(param); }); $modal.find('[data-modal-ok]').on('click', (ev) => { // モーダルの結果を設定して閉じる const result = $modal.find('input[type="text"]').val(); $modal.data('modal-result', result); $modal.modal('hide'); });