[Bootstrap3] モーダルからFormをSubmitする (Ajaxあり・なし)

JavaScriptAjax,Bootstrap3,jQuery

Bootstrap のモーダルダイアログの中にフォームを作って、モーダル内に入力されたデータをサブミットする方法。
submit ボタンを使って普通にサブミットすることも、 Ajax を使って非同期でサブミットすることもできる。親画面からデータを引き継ぐこともできる。

基本的なモーダルの使い方は、[Bootstrap3] モーダル・ダイアログの使い方 を参照してください。

必要なライブラリ

Bootstrap3 を使うために必要な css , js ファイルを用意する。
以下サンプルは CDN を使ってロードしている。

Bootstrap3 の CDN , jQuery の CDN ( Google 提供のもの)
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

本サンプルではカレンダー表示のために datepicker を使っているので、同様に使いたい場合は jQuery UI が必要。

<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

普通にサブミット (Ajaxなし)

モーダル内に form タグと、 submit ボタンを置く。
親画面に別の formsubmit ボタンが書いてあっても OK。ただし、この場合は、モーダルを開くためのボタンには、明示的に type="button" を書いて置かないとモーダルが開かない。

HTML

モーダル開くボタンが複数あっても、モーダル用のコードは 1 つで OK

<!-- モーダル開くボタン -->   
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#modalForm" data-cusno=1 data-visitday="2019-07-01">
    Open1
</button>
   
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#modalForm" data-cusno=2 data-visitday="2019-07-11">
    Open2
</button>
   
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#modalForm" data-cusno=3 data-visitday="2019-08-21">
    Open3
</button>
<!-- Modal の中身 -->
<div class="modal fade" id="modalForm" role="dialog">
  <div class="modal-dialog">
    <div class="modal-content">
      <!-- Modal ヘッダー -->
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">
          <span aria-hidden="true">×</span>
          <span class="sr-only">閉じる</span>
        </button>
      </div>
      <form role="form" id="form1" action="" method="POST">
        <!-- Modal ボディー -->
        <div class="modal-body">
          <div class="form-group">
            <label for="cusno">会員No</label>
            <input type="text" name="cusno" id="cusno" readonly>  
            <label for="oldday">来店日</label>
            <input type="text" name="oldday" id="oldday" readonly>
          </div>
          <div class="form-group">
            <label for="newday">新しい来店日</label>
            <input type="text" class="form-control" id="newday" name="newday" autocomplete="off"/>
          </div>
        </div>
        <!-- Modal フッター -->
        <div class="modal-footer">
          <button type="button" class="btn btn-default pull-left" data-dismiss="modal">閉じる</button>
          <button type="submit" class="btn btn-primary" id="chgDateSub" name="xxx" value="dateup">変更</button>
        </div>
      </form>
    </div>
  </div>
</div>

JavaScript (jQuery)

// カレンダー表示 (モーダルとは関係ないコード)
$('#newday').datepicker({
    dateFormat: 'yy-mm-dd',
});
// モーダルが開いた時の処理
$('#modalForm').on('show.bs.modal', function (event) {
    //モーダルを開いたボタンを取得
    var button = $(event.relatedTarget);
    //モーダル自身を取得
    var modal = $(this);
    //data-cusnoの値取得
    var cusnoVal = button.data('cusno');
    // input 欄に値セット
    modal.find('.modal-body input#cusno').val(cusnoVal);
    //data-visitdayの値取得
    var visitdayVal = button.data('visitday');
    modal.find('.modal-body input#oldday').val(visitdayVal);
});

PHP

// 「変更」ボタンが押されたとき
if (filter_input(INPUT_POST, "xxx") === "dateup") {
	$oldday = filter_input(INPUT_POST, "oldday");
	$newday = filter_input(INPUT_POST, "newday");
	$cusno = filter_input(INPUT_POST, "cusno");
	// DB 更新とか、何らかの処理
	...
	echo '会員No '.$cusno.' 様の来店日を '.$oldday.' から '.$newday.' に変更しました。';
}

Ajax でサブミット

HTML と PHP の処理はほぼ同じなのだが(ちょっとだけ変わっている)、コピペできるよう全コード書いておく。

HTML

<!-- 更新完了時に表示するメッセージ欄 -->
<p class='text-center bg-info' id="mess"></p>
<!-- モーダル開くボタン -->   
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#modalForm" data-cusno=1 data-visitday="2019-07-01">
    Open1
</button>  
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#modalForm" data-cusno=2 data-visitday="2019-07-11">
    Open2
</button>   
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#modalForm" data-cusno=3 data-visitday="2019-08-21">
    Open3
</button>
<!-- Modal の中身 -->
<div class="modal fade" id="modalForm" role="dialog">
  <div class="modal-dialog">
    <div class="modal-content">
      <!-- Modal ヘッダー -->
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">
          <span aria-hidden="true">×</span>
          <span class="sr-only">Close</span>
        </button>
      </div>
      <form role="form" id="form1">
        <!-- Modal ボディー -->
        <div class="modal-body">
          <div class="form-group">
            <label for="cusno">会員No</label>
            <input type="text" name="cusno" id="cusno" readonly>  
            <label for="oldday">来店日</label>
            <input type="text" name="oldday" id="oldday" readonly>
          </div>
          <div class="form-group">
            <label for="newday">新しい来店日</label>
            <input type="text" class="form-control" id="newday" name="newday" autocomplete="off"/>
          </div>
        </div>
        <!-- Modal フッター -->
        <div class="modal-footer">
          <button type="button" class="btn btn-default pull-left" data-dismiss="modal">Close
          </button>
          <button type="button" class="btn btn-primary" id="chgDateSub">変更
          </button>
        </div>
      </form>
    </div>
  </div>
</div>

普通のサブミットと変わったところは、更新完了時にメッセージを表示するために p タグを追加、 form タグから余計なものをとった(別にあっても構わない)、モーダル内の「変更」ボタンを type="button" にして余計なものを取った。そのため、 js で onクリックとか使ってボタンのアクションをひろう。

JavaScript (jQuery)

Ajax の処理を追加した。

// カレンダー表示
$('#newday').datepicker({
	dateFormat: 'yy-mm-dd',
});
$('#modalForm').on('show.bs.modal', function(event) {
	//モーダルを開いたボタンを取得
	var button = $(event.relatedTarget);
	//モーダル自身を取得
	var modal = $(this);
	//data-cusnoの値取得
	var cusnoVal = button.data('cusno');
	// input 欄に値セット
	modal.find('.modal-body input#cusno').val(cusnoVal);
	//data-visitdayの値取得
	var visitdayVal = button.data('visitday');
	modal.find('.modal-body input#oldday').val(visitdayVal);
	// 非同期のため、newday にデータが残るのでクリアする
	modal.find('.modal-body input#newday').val('');
});
// 「変更」ボタンをクリックしたとき
$('#chgDateSub').on('click', function() {
	console.log('click');
	var cusno = $('#cusno').val();
	var oldday = $('#oldday').val();
	var newday = $('#newday').val();
	$.ajax({
		url: "", // 送信先 URL
		type: "POST", // GET,POSTとか
		dataType: "text",
		data: { // 送信するデータ
			xxx: 'dateup',
			oldday: oldday,
			newday: newday,
			cusno: cusno
		}
	}).done(function(data) {
		// 通信成功時の処理
		// PHP から返ってきた値(メッセージ)を p タグにセット
		$('#mess').text(data);
	}).fail(function(data) {
		// 通信失敗時の処理
		console.dir(data);
	}).always(function(data) {
		// 常に実行する処理
		$("#modalForm").modal('hide'); // モーダルを閉じる
	});
});

続けてモーダルを開くと「新しい来店日」に前のデータが残るので、モーダルを開くたびにクリアする。
Ajax 通信後モーダルを閉じる処理を追加した。
PHP からはテキストメッセージしか返さないので、 dataType: "text" としている。返ってきたメッセージを p タグにセットして画面に表示している。

PHP

// 「変更」ボタンが押されたとき
if (filter_input(INPUT_POST, "xxx") === "dateup") {
	$oldday = filter_input(INPUT_POST, "oldday");
	$newday = filter_input(INPUT_POST, "newday");
	$cusno = filter_input(INPUT_POST, "cusno");
	// DB 更新とか、何らかの処理
	...
	echo '会員No '.$cusno.' 様の来店日を '.$oldday.' から '.$newday.' に変更しました。';
	exit;
}

最後に exit; を追加。
json で返したいなら json エンコードが必要。
必要に応じて header() 関数を使って Content-Type を指定する。



以上

Posted by Agopeanuts