Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display just the subcategories of the chosen category

This is the code I currently have:

<%= f.collection_select :category_id, Category.all, :id, :name, {prompt: "Choose a category"} %>
<%= f.collection_select :subcategory_id, Subcategory.all, :id, :name, {prompt: "Choose a subcategory"} %>

All it does is to display in one dropdown all the categories and in another all the subcategories. like this the drop downs.

Question: How to make just the specific subcategories appear depending on the chosen main category. With the code above, it shows all the categories and all subcategories.

Everything is linked in the model, the has_many, and belongs_to...and category_id and subcategory_id..everything is working properly, I just don't know how to show the specific subcategories within chosen category.

My attempt:

  <% if (Category.where(:name=>"Intro")) do |d| %>
    <% d.subcategories.each do |subcategory| %>
      <%= link_to subcategory.name, gigs_path(subcategory: subcategory.name) %>
    <% end %>
  <% end %>

This code gives an error. I though to say if, for example, the user picks the category called "Intro" than list all the "Intro subcategories". But it didn't work out - my code is obviously wrong.

Thank you.

like image 790
Mike McCallen Avatar asked Dec 25 '22 20:12

Mike McCallen


1 Answers

I assume you want this to happen without reloading the page? You won't get around a bit of JavaScript then. Here's the general workflow:

  • when the category dropdown is changed, send an Ajax request which will respond with JavaScript and insert the correct values into the Subcategory dropdown.

For the sake of this example I will just assume that your form (the model that belongs to a category) is a post. You didn't seem to mention the model.

Let's try this:

views/posts/_form:
I will wrap the subcategories selct box in a subcategories_select div, which enables us to replace the whole content later.

<%= f.collection_select :category_id, Category.all, :id, :name, { prompt: "Choose a category" }, id: "category_id" %>

<div id="subcategories_select">
 <%= f.collection_select :subcategory_id, Subcategory.all, :id, :name, { prompt: "Choose a subcategory" }, { disabled: true } %>
</div>

assets/javascripts/posts.js.erb

# select the element to watch for changes
$('form').on('change', '#category_id'), function() {
  var category_id = $(this).val(); # save the category_id set in the first dropdown

  $.ajax({
    url: "/categories/" + category_id + "/get_subcategories", # a custom route, see routes.rb further down
    type: "GET",
    dataType: "script", # we expect a response in js format
    data: { "category_id": category_id } # the only value we will need to get the subcategories
  });
});

config/routes.rb

# we need a custom route for our get_subcategories action
resources :categories do
  member do
    get :get_subcategories, defaults: { format: "js" }
  end
end

controllers/posts_controller.rb
Important: I assume that a category has_many subcategories and subcategories have a category_id, which meansbelong_to a category. If that's not the following won't make sense.

# our custom controller action
def get_subcategories
  @subcategories = Subcategory.where(category_id: params[:category_id])
end

app/views/posts/get_subcategories.js.erb
Here we will replace the content of our subcategories_select div and insert a collection_select with the appropriate options.

$('#subcategories_select').html("<%= j collection_select(:post, :category_id, @subcategories, :id, :title), { prompt: 'Select subcategory...' }, { disabled: false } %>");

Please note that I did this from the top of my head, so there might be errors, but this is one approach to dynamically populate select boxes, or in general change anything on a page without reloading.

like image 147
Michael Feihstel Avatar answered Dec 28 '22 06:12

Michael Feihstel