[0001]複数要素で構成されているカタマリを追加ボタンで非同期無限追加

■準備

名前、生年月日、性別などテキストボックス・ドロップダウンリスト・ラジオボタン・チェックボックスがある複数要素を追加ボタンのアクションで非同期追加します。追加数の制限はありませんのでWEBが固まらない限り無限に追加できます。

まずは追加したい要素の準備です。HTMLやView(フレームワークの場合)に追加したい要素を記述します。この例ではCakePHPフレームワークのViewなのでsample.ctpです。ポイントはコピーしたい要素群を囲むタグ(今回はtrタグです)にidをふっています。<tr id="child_addRow0">

また、コピーしたものをtbody要素の最後に挿入するため、ここもidをふっています。<tbody id="child_body">

他の要素もidとnameに「_0」の添え字をつけています。あとは通常通りのHTMLやViewです。

sample.ctp

              
<tbody id="child_body">
    <tr id="child_addRow0">
        <td><?php echo $this->Form->input_text("child_name_0", array("maxlength" => "50", "class" => "form-control")); ?>
        <td><?php echo $this->Form->input_text("child_name_kana_0", array("maxlength" => "50", "class" => "form-control")); ?>
        <td>
           <?php echo $this->Form->select('child_birthday_year_0',$this->Common->getYear(), array('class' => 'form-control select2 w100 birthday')); ?>
           年
    	   <?php echo $this->Form->select('child_birthday_month_0', $this->Common->getMonth(), array('class' => 'form-control select2 w100 birthday')); ?>
           月
           <?php echo $this->Form->select('child_birthday_day_0', $this->Common->getDay(), array('class' => 'form-control select2 w100 birthday')); ?>
           日
        </td>
        <td>
        	<?php $list_sex = CommonList::$sexList;
               foreach($list_sex as $k =>$v) {
                  echo '<div class="custom-control custom-radio">';
                  echo '<input class="custom-control-input" type="radio" id="child_sex'.$k.'_0" name="data[child_sex_0]" value="'.$k.'">';
                  echo '<label for="child_sex'.$k.'_0" class="custom-control-label">'.$v.'</label></div>';
               }
            ?>
        </td>
        <td>
        	<div class="custom-control custom-checkbox">
                <?php echo $this->Form->input('child_sukusuku_flg_0', array('type' =>'checkbox','div' => false,'class'=>'custom-control-input'));?>
                <label for="child_sukusuku_flg_0" class="custom-control-label">有</label>
            </div>
        </td>
        <td>
            <a class="btn btn-danger btn-sm" href="javascript:void(0)" id="btn-delete_child_0">
            <i class="fas fa-trash"></i>削除</a>
        </td>
    </tr>
</tbody>
              
            

次に例で作ったHTMLに追加ボタンを用意します。要素追加アクションを行うボタンです。onclick="javascript:plusRowAdd('child')"onclickイベントを用意しました。ボタンを押すと引数childでplusRowAdd関数を実行します。

sample.ctp

              
<div class="txtR">
   <button type="button" class="btn btn-success w100 mt20" onclick="javascript:plusRowAdd('child')">追加する</button>
</div>
              
            

次に例で作ったHTMLからjsを読み込みます。この例ではjs名を[commonRowAdd]にしています。ご自身の環境に合わせてjsファイルを配置してください。

sample.ctp

              
<script src="js/commonRowAdd.js"></script>
              
            

要素追加数(添え字管理用)を保持しておくためのhiddenも追加しておきます。

sample.ctp

              
<input id="child_cnt" name="child_cnt" type="hidden" value="<?php echo $formChildCnt; ?>">
              
            

■Jquery作成

準備完了です!いよいよ先ほど作成したjsに関数を作成していきます。要素追加アクションを行うボタンでセットした関数を作成しますので、この例では関数名は[plusRowAdd]です。

commonRowAdd.js

              
function plusRowAdd(setcase) {
	setcntName = setcase+'_cnt';
	insertCnt = parseInt($("input[name="+setcntName+"]").val())+1;
	addstring = "";

	if(setcase == "child"){
		var obj = $('#child_addRow0').clone().attr("id",'child_addRow'+insertCnt);
		//radioとcheckboxのlabelのfor変更
		obj.find('.custom-control-label').each(function( index, value ) {
			forstr = $(this).attr("for");
			setfor = forstr.replace(0,insertCnt);
			$(this).attr("for",setfor);
		});
		//textのidとname変更
		obj.find('.form-control').each(function( index, value ) {
			str = $(this).attr("id");
			setStr = str.replace(0,insertCnt);
			$(this).attr("id",setStr);
			str = $(this).attr("name");
			setStr = str.replace(0,insertCnt);
			$(this).attr("name",setStr);
		});
		//radioとcheckboxのidとname変更
		obj.find('.custom-control-input').each(function( index, value ) {
			str = $(this).attr("id");
			setStr = str.replace(0,insertCnt);
			$(this).attr("id",setStr);
			str = $(this).attr("name");
			setStr = str.replace(0,insertCnt);
			$(this).attr("name",setStr);
		});
		//hiddenの変更
		obj.find('[name="child_addRowH0"]').attr('name', 'child_addRowH'+insertCnt);
		obj.find('[id="child_sukusuku_flg_0_"]').attr('id', 'child_sukusuku_flg_'+insertCnt+'_');
		obj.find('[id="child_sukusuku_flg_'+insertCnt+'_"]').attr('name', 'data[child_sukusuku_flg_'+insertCnt+']');
		//削除ボタンの変更
		obj.find('[id="btn-delete_child_0"]').attr('id', 'btn-delete_child_'+insertCnt);

	    //要素の後ろにコピーした要素を追加する
		$('#child_body').append(obj);
		//表示するため、非表示CSSを削除
		$('#child_addRow'+insertCnt).removeClass("nonDisp");
	}
	$("input[name="+setcntName+"]").val(insertCnt);
}
              
            

現在の最終添え字管理をhidden[child_cnt]から参照し、プラス1をしてinsertCntに添え字をセットしています。

var obj = $('#child_addRow0').clone().attr("id",'child_addRow'+insertCnt);ここでJqueryのcloneを利用し、idがchild_addRow0の要素をまるっとコピーし、idの添え字を変えています。

コピーしたものをobjにセットしましたので、obj.findでコピー要素内で検索をし、それぞれ添え字を変えています。

ご自身の環境に合わせて変更してください。このサンプルは非同期で追加・削除があり、POSTで登録処理をするために必要なものが記述されています。

最後にコピーし修正した要素群をtbodyタグのidのchild_bodyの後ろに追加するためappendしています。

$("input[name="+setcntName+"]").val(insertCnt);次の要素群追加のための添え字管理のためのhiddenセットを忘れずに。

完成です!!関連記事も追加しています。