I wanted to create a three dropdown selects category>subcategory>susubcategory I have followed this method 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 %>