Home > Software engineering >  Rails 7 stimulus Hide dropdown if empty
Rails 7 stimulus Hide dropdown if empty

Time:11-21

I have a 3 category/subcategory/subsubcategory dependant dropdowns everything works fine but I have a small issue. the second dropdown (subcategories) does not always have subsubcategories so I want to hide the last dropdown and only show it when there is a subsubcategory so it only shows based on the user selection of the subcategory

I would appreciate if someone can help.

enter image description here

my categories table

  create_table :categories do |t|
          t.string   "name",        limit: 255
          t.text     "description", limit: 65535
          t.integer  "parent_id",   limit: 4
          t.boolean  "important",                 default: false
          t.integer  "position",    limit: 4,     default: 0
          t.timestamps
        end

in modules category.rb

 class Category < ApplicationRecord

        validates :name, presence: true
        has_many :jobs
        belongs_to :parent, foreign_key: :parent_id, class_name: 'Category' , :optional => true
        has_many :subcategories, foreign_key: :parent_id, class_name: 'Category'
        has_many :subsubcategories, foreign_key: :parent_id, class_name: 'Category'
end
    

in modules job.rb

 class Job < ApplicationRecord

 validates :title,:category_id, :description, presence: true
 validates :category, :presence => true

 belongs_to :user
 belongs_to :category , -> { order("name") }
 belongs_to :subcategories, class_name: "Category"
 belongs_to :subsubcategories, class_name: "Category"

  
end

dropdown_controller.js

import { Controller } from "@hotwired/stimulus";

// connect to data-controller="dropdown"

export default class extends Controller {
    submit () {
           this.element.requestSubmit();
 
    }
 
}

in my jobs_controller.rb

  class JobsController < ApplicationController
 
  before_action :authenticate_user!, except: [:index, :show]
  before_action :set_categories

 
  
  def index
    @jobs = Job.all

   
  end
 

 
 
  def new
    @category = Category.find_by(id: params[:category])
    @categories = Category.where(parent_id: nil)  
    @subcategories = @category.subcategories if @category
    @subsubcategories = Category.where(:parent_id => params[:subcategories])  
     @job = Job.new
  

   
  end


  def create
  
  @job = Job.new(job_params.merge({ user: current_user }))
    if @job.save
     format.html { redirect_to root_path, notice: "Job was successfully created." }
    else
    render :new, status: :unprocessable_entity
    
  end
end

private
def job_params
  params.require(:job).permit(:title, :description,:category_id).merge(user: current_user)

end

 



 def set_categories
  @category = Category.find_by(id: params[:category].presence)
  @subcategory = Category.find_by(id: params[:subcategories])
  @subsubcategory = Category.find_by(id: params[:subsubcategories])

 end
end

views/jobs/new.html.erb

  <%= turbo_frame_tag "form" do %>
 
 <%= form_tag new_job_path, method: :get, data: { controller: "dropdown", action: "change->dropdown#submit" } do %>
 <%= select_tag  :category, options_from_collection_for_select(@categories, "id", "name", @category&.id ), prompt:  "Select a category" %>
 <%= select_tag  :subcategories, options_from_collection_for_select(@subcategories  || [], "id" , "name", @subcategory&.id), prompt:  "Select a subcategories category" %>
     <%= select_tag  :subsubcategories, options_from_collection_for_select(@subsubcategories || [], "id" , "name", @subsubcategory&.id), prompt:  "Select a subsubcategories category" %>
      
  <% end %>
 
  <% end %>

  

CodePudding user response:

Why don't you hide it definitely. Like changing views/jobs/new.html.erb to something like this :

<%= turbo_frame_tag "form" do %>
  <%= form_tag new_job_path, method: :get, data: { controller: "dropdown", action: "change->dropdown#submit" } do %>
    <%= select_tag  :category, options_from_collection_for_select(@categories, "id", "name", @category&.id ), prompt:  "Select a category" %>
    <%= select_tag  :subcategories, options_from_collection_for_select(@subcategories  || [], "id" , "name", @subcategory&.id), prompt:  "Select a subcategories category" %>
   <% if @subsubcategories.any? %>
    <%= select_tag  :subsubcategories, options_from_collection_for_select(@subsubcategories || [], "id" , "name", @subsubcategory&.id), prompt:  "Select a subsubcategories category" %>
   <% end %>   
  <% end %>
<% end %>

CodePudding user response:

I actually got it working exactly as I want without Javascript:

 <% if [email protected]? %>

  <%= select_tag   :subsubcategories , options_from_collection_for_select(@subsubcategories || [], "id" , "name", @subsubcategory&.id), prompt:  "Select a subsubcategories category"  %>
 
  <% end %>
  • Related