Neil Neil - 3 months ago 8
Javascript Question

Change second select list based on first select list value in rails

Updated with answer code at bottom

For second select box, show select options for only those

staff members
associated to the selected
team
.

Form:

enter image description here   




Example case: A user selects another team. The staff member select options updates to display only those staff members associated with that selected team.

enter image description here

I know the solution is with javascript, but I'm having trouble applying it within a rails environment. I am aware of this question but am still having trouble applying it to my rails app.




Code

#app/controllers/task_notes_controller.rb
...
def new
@task_note = TaskNote.new
@teams = Team.all.includes(:staff_members)
end
...





#app/views/task_notes/_form.html.erb
...
<%= select_tag('team', options_from_collection_for_select(@teams, :id, :name ) ) %>

<div class="field">
<%= f.label :staff_member_id %><br>
# Currently displays all staff members on every team, no matter what team is selected.
<%= f.collection_select :staff_member_id, StaffMember.all, :id, :first_name %>
</div>
...





#app/assets/javascripts/task_notes.js
$(document).ready(function(){

$("#team").on('change', function(){
alert("The new team id is: " + $(this).val() );
# The value (the id of the team) does update on selection option change.
# Now I need to specify that I want the select options for the staff members
# select box to update and show only staff members with this team_id
});

});

Answer

First you fire an ajax call to your controller. (Keep in mind that this url from the ajax call must exist in your routes).

$(document).ready(function() {
  $("#team").on('change', function(){
    $ajax({
      url: "populate_other_list",
      type: "GET",
      data: {team_id: $(this).val()},
      // Callbacks that will be explained
    })
  });

Next you make your action inside your controller.

def populate_other_list
  team_id = params[:team_id]
  @staff = Staff.find_by team_id: team_id
  respond_to do |format|
    format.json { render json: @staff }
  end
end

With this, on your success callback of your ajax call, you get a JSON object with your list. So you need to clear the staff select and create the options and append to it.

// Ajax call
success: function(data) {
  $("#staff_member_id").children().remove();
  // Create options and append to the list
}
// Rest of Ajax call

As you can see, i didn't put the code that create the options and put them inside the list, but a simple search will have plenty of results about this. The idea is simple though.