Search code examples
jqueryajaxruby-on-rails-4collection-select

Rails 4 Dynamic Collection_Select


This seems to be a pretty popular question here, though I have yet to find a tutorial or thread that works for me. I have a two dropdown menus in a form, Team Type and User Role, where User Role is dependent on Team Type. The options for Team Type are stored in the model as an array, since there are only 5 choices (Artist, Venue, Promoter, Independent, Other). What I would like to do is source the selections for User Role from the model as well, with the proper array selected depending on the Team Type. Is this possible, or do I need to create models for each Team Type and pass an ID to a join table to select the proper User Role? Thank you.

Model

class WaitingList < ActiveRecord::Base
  COMPANIES = ['—Select—', 'Artist Team', 'Venue Team', 'Promoter', 'Independent', 'Other']
  ARTIST_TEAM = ['-Select-', 'Artist', 'Manager', 'Tour Manager', 'Production Manager', 'Agent', 'Other']
  VENUE_TEAM = ['-Select-', 'Artist Liason', 'Stage Manager', 'Production Manager', 'Owner', 'Other']
  PROMOTER = ['-Select', 'Talent Buyer', 'Other']
  INDEPENDENT = ['-Select', 'Agent', 'Photo/Video', 'Tour Manager', 'Manager', 'Other']
end 

Form

<div class="form--col">
  <label>Team Type</label>
    <div class="dropdown-wrapper">
      <%= f.collection_select :company_type, WaitingList::COMPANIES, :to_s, :to_s, {:include_blank => false}, {:class => "form--dropdown -team_type"} %>
    </div>
</div>

<div class="form--col -inactive">
  <label>Main Role</label>
    <div class="dropdown-wrapper">
      <%= f.collection_select :user_type, WaitingList::USERS, :to_s, :to_s, {:include_blank => false}, {:class => "form--dropdown", :disabled => "disabled"} %>
    </div>
</div>

Solution

  • I think you should do it ajax request by adding javascript onChange function. Also add a new method to handle this ajax request

    Form

    <div class="form--col">
      <label>Team Type</label>
      <div class="dropdown-wrapper">
        <%= f.collection_select :company_type, WaitingList::COMPANIES, :to_s, :to_s, {include_blank: false}, {onchange: "getRoles();", class: "form--dropdown -team_type"} %>
      </div>
    </div>
    
    <div class="form--col -inactive">
      <label>Main Role</label>
      <div class="dropdown-wrapper">
        <%= f.collection_select :user_type, {}, {prompt: 'Main Role'} {:class => "form--dropdown", :disabled => "disabled"} %>
      </div>
    </div>
    

    Javascript file

    function getRoles() {
      var currentRole = $('#company_type :selected').val(); 
      $.ajax({
         url: '/waiting_lists/'+ currentRole +'/get_role',
         dataType: "json",
         success: function(data) {
           $('#user_type').html('');
           for (i in roles) {
             if (roles[i] != undefined) {
               $('#user_type').append("<option value=\""+roles[i]+"\">"+roles[i]+"</option>");
             }  
           }
         } 
      });      
    }
    

    Controller

    I added a route for waiting_lists controller

      def get_role()
        if params[:role]
          case params[:role]
          when 'Artist Team'  
            roles = WaitingList::ARTIST_TEAM
          when 'Venue Team'
            roles = WaitingList::VENUE_TEAM
          when 'Promoter'
            roles = WaitingList::PROMOTER
          when 'Independent'
            roles = WaitingList::INDEPENDENT
          when 'Others'
            roles = []
          end      
          render json: {roles: roles}
        end 
      end
    

    Routes

    Added route for waiting_lists controller

    resources(:waiting_lists) do
      collection do
        get(':role/get_role', action: :get_role)
      end
    end
    

    Hope this is helpful.