Search code examples
ruby-on-railspartials

How to structure navbar with side bar in ruby on rails


Picture of my application

In my application above I have a top navbar and a side bar. When a user click the sell tab in the topnav bar it directs them to the sell page which contains the sidebar, all other pages in the navbar do not contain the side bar. When a user clicks on one of the tabs on the sidebar it should show some content on right of the sidebar. The issue Im having is im not sure exactly how to strutcure this in ruby on rails.

I currently have an index page in my sell controller that contains the sidebar

sellcontroller.rb

class SellController < ApplicationController
  
  def index
  end
end

index.html.erb

<div class="container-fluid">
    <div class="row flex-nowrap " >
            <div class="col-auto col-md-3 col-xl-2 px-sm-2 px-0 float-left position-sticky">
                <div class="d-flex flex-column align-items-center align-items-sm-start px-3 pt-2 text-white min-vh-100">
                    <a> My Items<a/>
                    <ul class="nav nav-pills flex-column mb-sm-auto mb-0 align-items-center align-items-sm-start" id="menu">
                        <li class="nav-item">
                            <a class="nav-link active" aria-current="page" href="#">Sale</a>
                        </li>
                    
                        <li>
                            <a href="#" class="nav-link px-0 align-middle">
                                <i class="fs-4 bi-table"></i> <span class="ms-1 d-none d-sm-inline">Sold</span></a>
                        </li>
                        
                    </ul>
                    
                    
                </div>
            </div>
            <div class="col py-3">
                **content area**
        
            </div>
    </div>
 </div>


 
  

I also have the sale and sold partials

_sale.html.erb

<div class="container-fluid">
   
    <p>Sale content</p>  
    
</div>


_sold.html.erb

<div class="container-fluid">
   
    <p>Sold content</p>  
    
</div>


My current plan is to use logic in sell_helper.rb file to render the appropriate content based on what tab was clicked in the sidebar but I feel there should be a better way to do this.

I would also like the url to change based on what tab in the side bar was clicked, so for example - localhost:3000/sell/sale. However if I continue with this approach that won't be the case as it shows localhost:3000/sell/index since the partials are technically nested in the index page.

I have thought of changing the sale and sold to regular .html.erb files instead of partials but I dont know how I would fit the sidebar component around it.


Solution

  • What you want is a full template for each link, each template would render a shared sidebar partial plus its content. You can fix urls in your routes and also add extra routes for new links which you then add to a shared sidebar.

    Rails.application.routes.draw do
      get "sell/sale", to: "sell#sale"
      get "sell/sold", to: "sell#sold"
    
      # # or if you want to get fancy to do the same
      # scope path: :sell, controller: :sell, as: :sell do
      #   get :sale
      #   get :sold
      # end
    end
    
    # app/controllers/sell_controller.rb
    
    class SellController < ApplicationController
    end
    
    # app/views/sell/sale.html.erb
    
    <div class="flex">
      <%= render "sell/sidebar" %>
      <div> sale content </div>
    </div>
    
    # app/views/sell/sold.html.erb
    
    <div class="flex">
      <%= render "sell/sidebar" %>
      <div> sold content </div>
    </div>
    
    # app/views/sell/_sidebar.html.erb
    
    <% is_active = ->(name) { action_name == name } %>
    
    <aside class="flex flex-col">
      <%= link_to "sale", sell_sale_path, class: {"active": is_active.("sale")} %>
      <%= link_to "sold", sell_sold_path, class: {"active": is_active.("sold")} %>
    </aside>