Home > Net >  Creating three Dependent Drop-Downs With Ruby on Rails 7 and turbo/stimulus
Creating three Dependent Drop-Downs With Ruby on Rails 7 and turbo/stimulus

Time:11-16

I wanted to create a three dropdown selects category>subcategory>susubcategory I have followed this method here enter image description here

my categories table

create_table :categories do |t|
      t.string   "name",        limit: 255
      t.text     "description", limit: 65535
      t.references  "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, uniqueness: true
    has_many :jobs
    belongs_to :parent_category, foreign_key: :parent_id, class_name: 'Category'
    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") }
 
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

  before_action :authenticate_user!, except: [:index, :show]
  before_action :set_categories

 
  
  def index
    @jobs = Job.all
  
  end
 
 
  def new
    @categories = Category.where(parent_id: nil)  
    @subcategory = @subcategory&.category || []
    @subcategories = @subcategories&.subcategories || []
    @subsubcategories = @subsubcategories&.subsubcategories || []
    @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)
  @categories = Category.find_by(id: params[:category].presence)
  @subcategories = Category.find_by(id: params[:category].presence)
  @subsubcategories = Category.find_by(id: params[:subcategories].presence)

 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", @category&.id), prompt:  "Select a subcategories category" %>
 <%= select_tag  :subsubcategories, options_from_collection_for_select(@subsubcategories, "id" , "name", @category&.id), prompt:  "Select a subsubcategories category" %>

 
<% end %>
<% end %>

CodePudding user response:

I think that you miss update select_tag after request successfully.

you create a new file views/jobs/new.turbo_stream.erb

Ex: The select_tag has category_id

   <%= turbo_stream.update "category_id" do %>
      <%= select_tag  :category, options_from_collection_for_select(@categories, "id", "name", @category&.id ), prompt:  "Select a category" %>
   <% end %>

Make sure select_tag selected value with @category&.id (ex: @category&.id = 1)

I done it but i have 2 select_tags.

https://drive.google.com/file/d/1MBY3T0_O2TAE6zFUywDsEoIOjnxr1hMy/view?usp=share_link

P/S: Contact me if you wanna know anymore.

CodePudding user response:

This was the solution to the problem:

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 %>
  • Related