RailsとBootstrapでサイドバーにVerticalな展開式のnavを作る方法


Bootstrapでサイドバーにカテゴリー一覧を出し、親要素と子要素をネストさせたい👇

展開(collapse)はBootstrapでは#sidemenu1のようなIDをターゲットにするのが決まりらしい。


        <div class="col-md-3 col-xl-2 bd-sidebar">
            <nav class="navbar navbar-expand-lg navbar-light bg-light">
                <a class="navbar-brand">カテゴリー</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarNavDropdown">
                    <ul class="navbar-nav flex-column">             
                        <% @categories.each do |category| %>
                            <li class="nav-item">
                                <a class="nav-link collapsed text-truncate" href="/categories/<%= category.id %>" data-toggle="collapse" data-target="#submenu<%= category.id %>"><i class="fa"></i><span class="d-none d-sm-inline"><%= category.name %></span></a>
                                <div class="collapse" id="submenu<%= category.id %>">
                                    <ul class="flex-column pl-3 nav">
                                        <% category.children.each do |child| %>
                                            <li class="nav-item"><a class="nav-link" href="/categories/<%= child.id %>"><span><%= child.name %></span></a></li>
                                        <% end %>
                                    </ul>
                                </div>
                            </li>
                        <% end %>                   
                    </ul>
                </div>
            </nav>
        </div>

最初から展開したい場合

親カテゴリのa要素?にaria-expanded="true"属性?を付与
トグルターゲットであるdiv要素にclass="collapse show"を付与

                                <a class="nav-link text-truncate" href="/categories/<%= category.id %>" data-toggle="collapse" data-target="#submenu<%= category.id %>" aria-expanded="false"><i class="fa"></i><span class="d-none d-sm-inline"><%= category.name %></span></a>
                                <div class="collapse show" id="submenu<%= category.id %>">
                                    <ul class="flex-column pl-3 nav">
                                        <% category.children.each do |child| %>
                                            <li class="nav-item"><a class="nav-link" href="/categories/<%= child.id %>"><span><%= child.name %></span></a></li>
                                        <% end %>
                                    </ul>
                                </div>

基本は公式ドキュメントの nav > vertical をもとにしている。
https://getbootstrap.com/docs/4.5/components/navs/#vertical

ナビに子要素をもたせて展開させるにはこちらを参考にした。孫まであるケースなので、おそらく親と子だけしか使わなかった今回は不要なクラスや属性を付与しちゃっているかも。

ただしカテゴリー親要素と子要素の取得は、カテゴリーを多階層化できるGemであるAncestryによる記法で取得している。

post_controller.rb
    def index
        @categories = Category.where(id: Category.pluck(:ancestry).compact.map { |e| e.split('/') }.flatten.uniq)
    end