初めまして、kuramasaです。
初回の投稿から個人的に難しめの内容ですが、CakePHPでTwitterに近いWEBアプリを制作した時に、繰り返し処理(foreach文など)で出力した投稿にメニューボタンをつけ、クリックするとモーダルが現れ、「詳細を見る」・「編集」・「削除」などの選択肢が出てくるようにしたかったのですが、中々上手くいかなかったので、それを解決した方法を書いていこうと思います٩( ‘ω’ )و
はじめに
モーダルの仕組み、カスタムデータ属性の記述の仕方、jQueryまたはJavaScriptの文法を理解しているとササっとできたかもしれませんね…汗
先に読んでおくと理解しやすい記事
※後半にも同じリンクを貼っています。
jQueyの要素を指定する際の文法的な話です。
http://www.jquerystudy.info/reference/selectors/equals.html
上のリンクの補足説明として、必要な情報です。式展開という内容です。
http://song-of-life.hatenablog.com/entry/2018/05/26/235057
今回の私の記事と同じモーダルを作成している方がいたので、その方のリンクも貼っておきます。
http://cly7796.net/wp/javascript/create-a-modal/
概要
まず、大まかな概要としては、
1. 各投稿に付いているメニューボタンをクリック
2. CSSのdisplay:none;で隠してあるモーダルの要素たちをjQueryのfadeIn();で表示
と考えたわけですが、
ここで注意したいのがメニューボタンと表示させたモーダルの中身です。
この2つが投稿データとして関連付いていて、クリックしたメニューボタンと表示させたい選択肢をしっかりと識別させる必要がありました。
どういうことかと言うと、ID=1の投稿のメニューボタンをクリックするとその投稿ID=1に対する選択肢が現れるようにすると言うことです。
これをせず安直にモーダルを実装した結果、どの投稿のメニューボタンをクリックしても一番最新の投稿の選択肢が出てきており、よく分析すると繰り返し処理した投稿の選択肢が何枚も重なっているような状況になっていました。
解決方法
色々試行錯誤して閃いたのが、
投稿のユニークなIDとカスタムデータ属性の組み合わせです。
上手くいったコードを以下に載せますので、コード上のコメントにある説明も一緒に読んでみてください!
HTMLとPHPのコード
HTMLとPHPの記述が以下の通りです。
class=”current_nav_icon”とclass=”current_action_nav”のli要素にあるdata-madal~とありますが、ここにカスタムデータ属性を使っています。
<?php foreach($tweets as $tweet):?> <!--繰り返し処理-->
<ul class=" mytweet_item ">
<li class="current_nav_icon " data-modal-link="<?= $tweet->id ?>"> //←ここ➀!! <i class="fas fa-angle-down"></i> </li> <li class="current_action_nav " data-modal-content="<?= $tweet->id ?>"> //←ここ➁!! <!--ここからli要素にulタグを入れています--> <ul class="menu"> <li class="action"> <!--CakePHPのお作法に従って記述した書き方なので少し特殊ですがこういう意味です--> <!--ここはli要素にaタグでテキストがviewというタグを入れており、リンクに投稿のidをGET送信し、投稿の詳細ページへ繋がっています。--> <?= $this->Html->link(__('view'), ['action' => 'view', $tweet->id]) ?> </li> <li class="action"> <!--ここはli要素にaタグでテキストがeditというタグを入れており、リンクに投稿のidをGET送信し、投稿の編集ページへ繋がっています。--> <?= $this->Html->link(__('edit'), ['action' => 'edit', $tweet->id]) ?> </li> <li class="action"> <!--ここはli要素にaタグでテキストがdeleteというタグを入れており、リンクに投稿のidをPOST送信し、投稿を削除する処理を行います。--> <?= $this->Form->postLink(__('delete'), ['action' => 'delete', $tweet->id], ['confirm' => __('Are you sure you want to delete # {0}?', $tweet->id)]) ?> </li> <li class=" close-menu"> <i class="fa fa-2x fa-times"></i> </li> </ul> //menu-end <!--liの入れ子になっているul終了--> </li> <!--current_action_nav--end--> </ul> <!--mytweet_item--end--> <?php endforeach;?>
jQueryのコード
jQuery の記述は以下のようになります。
$('.current_nav_icon').click(function () { //メニューアイコンクリック
var target = $(this).data('modalLink');
//変数targetにクリックしたメニューボタンの
//data-modal-linkというカスタムデータクラスに入っている投稿のidを入れる
//HTMLのコードの ←ここ➀!! とコメントしている行
$('[data-modal-content = ' + target + ']').fadeIn();
});
//targetに入ったidとdata-modal-contentというカスタムデータ属性に入った
//投稿のidが同じ要素をフェードインで表示
//HTMLのコードの ←ここ➁!! とコメントしている行
$('.close-menu').click(function () {
$('.current_action_nav').fadeOut();
//クローズボタンをクリックして、フェードインしたものをフェードアウトで消す
});
CSSのコード
cssのコードは以下のようになります。
/* view/edit/delete action モーダル start------------------------------------- */
.admin_nav_icon,
.current_nav_icon,
.other_nav_icon{
position:absolute;
left:40%;
}
/* モーダル背景 */
.admin_action_nav,
.current_action_nav,
.other_action_nav
{
position:fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 100;
display: none;
}
/* モーダル本体 */
.menu {
position: absolute;
top: 40%;
left: 35%;
width: 30%;
height: auto;
margin:0;
text-align: center;
list-style: none;
background-color: rgb(170, 170, 170);
border-radius: 10px;
}
.action{
width:100%;
border-radius: 10px;
}
.action a{
color:rgb(255, 255, 255);
display:inline-block;
font-size:20px;
width:100%;
padding:5% 0;
}
.action:hover{
background-color:rgb(255, 255, 255);
}
.action a:hover{
color:rgb(0, 0, 0);
}
/* 閉じるボタン */
.fa-times {
font-size:18px;
position: absolute;
top: -20%;
left:100%;
color: rgb(0, 0, 0);
background-color:rgb(255, 255, 255);
border-radius:10px;
width:auto;
height:auto;
padding:2.5% 3%;
cursor: pointer;
z-index: 100;
}
/*view/edit/delete action モーダル end ------------------------------------- */
まとめ
jQueryとカスタムデータ属性を扱うことで、より柔軟な操作をすることができるなと感じました。当初、JSONでデータを渡す方法しかないのでは?と思っていましたが、ProgateのjQueyのコースを思い出し、そこから取り掛かりました。発想の仕方で色々なことができるのがプログラミングの楽しさだなぁと改めて感じました。
jQueryのfadeIn();をしている要素の記述に関する説明はこちらのリンクにありますが、ここでは’値’としていて変数を入れる場合には少し記述の仕方が違うようです。
変数をカッコに入れる方法は別のリンクで一段下に載せておきます!
http://www.jquerystudy.info/reference/selectors/equals.html
jQueryの式展開という用語で調べるとヒントが出てきそうですが、今回は以下の記事を参照しました。
http://song-of-life.hatenablog.com/entry/2018/05/26/235057
上のリンクを理解した上で同じモーダル操作を行なっている方のリンクも貼っておきます。
http://cly7796.net/wp/javascript/create-a-modal/