【Bootstrap/Rails】popoverのdata-contentの中身をHelperに切り出してみた。
こんにちは、マリンです。
今回はBootstrapのpopoverです。
popoverはtitle
に表示するタイトル。data-content
に表示する内容を書きます。
でも長い内容をタグ内に書きたくないでしょ!
ってなわけでRailsのHelperにメソッド切って表示内容を切り出してみました。
注)HTML上ではベタ書きになっちゃいますけど。
概要
- 環境 -
Rails5
Bootstrap3
- 例に使うテーブル構造 -
Usersテーブル
id
name
Childrenテーブル
id
name
user_id
- 概要 -
Userの名前をクリックすると、
ポップオーバーでChildrenの名前が表示されるようにします。
この時data-content
の中身が複雑になるので、
Helperにメソッドを切ってそれをdata-content
に渡します。
詳細
そもそもなんでこんなことになるのか?ちょっと詳細を説明します。
まず前提として、対象のページはindex.html.erb
で、
Userの名前はUser.all
をeach
で回して表示しているとします。
さらにChildrenは複数いる可能性があります。
そこで問題となるのが、
どのUserの子供であるかを特定するために
user
を渡す必要があること。Childrenは
user.children
の配列になること。その配列から名前を取得して表示するには、ループを回す必要があること。
ポップオーバーの内容は複雑になる場合、別エリアに切り出すことも可能です。
しかし今回の場合、まず一番外側でUser.all
をループしています。
切り出すにはこのループの外になるでしょう。
となると1番のどのUserかを特定するuser
を渡すのが大変です。
Ajaxを駆使してコントローラに値を渡して〜・・・なんてことが予想されます。
2、3番は表示内容が複雑になる理由です。
てことでHelperにメソッドを切ってみてはどうか?となったわけです。
ちなみに子の名前は一人一人改行して表示します。
HTML上はベタ書きになってしまいますが、コードはすっきりします。
ソースコード
さて前置きが長くなりましたが、ここから本題です。
まぁやってることは真新しいことではないのですが・・・
ControllerとModelは特に特筆することはないので、コードだけで解説は省略します。
Controller
# controllers/users_controller.rb def index @users = User.all end
Model
# user.rb has_many :children # child.rb belongs_to :user
View
<!-- views/users/index.html.erb --> <% @users.each do |user| %> <button class="btn" data-html="true" data-toggle="popover" title="子ども" data-cotent="<%= children_popover(user) %>"> <%= user.name %> </button> <% end %>
まずbuttonタグの中にあるdata-html="true"
をご覧ください。
今回のメソッド切り出しとは直接関係はありませんが、
これを入れることでポップオーバーの中で改行<br>
を使うことができるようになります。
次に本題のdata-content="<%= children_popover(user) %>"
です。
このerb表記の中身が、後述のHelperに切り出すメソッド名です。
引数にuser
を渡していることにご注目ください。
別エリアへの切り出しではないため、大枠のループのuser
をそのまま使うことができます。
Helper
# helpers/users_helper.rb def children_popover(user) users_children = [] user.children.each do |child| users_children << child.name end users_children.join("<br>") end
まず最初に子どもの名前を入れる空の配列を用意します。
そしてuser.children
のループを回し、
その中で名前を先ほどの配列に格納していきます。
最後にループの外で出来上がった配列を、
区切り文字に<br>
改行を指定して返します。
これを使うために先ほどViewでdata-html="true"
を指定しました。
解説は以上になります。
まとめ
今回は値の取得などにたいした時間がかからないものでしたのでこの方法を使用しました。
しかし、表示する値の取得に時間がかかるようでしたら、
やはり別エリアに表示内容を切り出し、
値の取得にはAjaxを使って行うなどの方法をとった方が良いかと思います。
私も機会がありましたら挑戦してみようと思います。
ちなみに、今回の検証でpopoverを使用するためにclass="btn"
が必ず必要だったのですが、
これは仕様でしょうか?それとも私の設定ミスでしょうか?
どなたかわかる方いらっしゃいましたら是非教えてください。
よろしくお願い致します。