Dynamic select dropdown Rails 5 / AJAX
Asked Answered
B

1

5

I'm trying to make a three input select menu that allows a user to filter down to one course in the database to select. So the user first selects the location, and based on that selection is given all the options of courses that are in that location. He can then press select and be brought to that course. The dynamic part has my mind bent a little. I'd love any help if possible. I understand some AJAX will probably be required but I'm lost on that end. Any advice please.

Code so far. View.

<div class="row no-gutters wow slideInUp" data-wow-duration="1s">
  <div class="col-md-12 home-form">
    <form class="form-inline">
      <select class="custom-select mb-0 mr-sm-0 mb-sm-0">
        <option selected>Location</option>
        <%= @locations.each do |location| %>
                <option value="<%= location.id %>"><%= location.header %></option>
        <% end %>
      </select>
      <select class="custom-select mb-0 mr-sm-0 mb-sm-0">
        <option selected>Course Type</option>
        <%= @courses.each do |course| %>
                <option value="<%= course.id %>"><%= course.course_type %></option>
        <% end %>
      </select>

      <select class="custom-select mb-0 mr-sm-0 mb-sm-0">
        <option selected>Course</option>
        <%= @courses.each do |course| %>
                <option value="<%= course.id %>"><%= course.title %></option>
        <% end %>
      </select>
      <button type="submit" class="btn btn-primary">Submit</button>
    </form>
  </div>
</div>

Controller just pulls in variable for all locations and courses.

Then models have associations as below.

course

belongs_to :location

location

has_many :courses, dependent: :destroy

I can see all the courses and locations from the dropdown but I need to be able to select a location and then only see courses that are in that location please. If any AJAX code is responded i'd love an explanation of what's happening in the code if you have time. Thanks a million.

enter image description here

Bronchiectasis answered 26/1, 2018 at 14:10 Comment(0)
R
8

You can follow my instructions to add dynamic dependent drop down list to your rails applications -

Step -1. Add an action to route file for getting all courses for a specific location.

# config/routes.rb

Rails.application.routes.draw do

  get 'get_courses_by_location/:location_id', to: 'courses#get_courses_by_location'  
  get '/course_search' => 'courses#course_search'

 end

Step -2. Create courses controller with get_courses_by_location action

# app/controllers/courses_controller.rb

class CoursesController < ApplicationController

  def get_courses_by_location
    @courses = Course.where("location_id = ?", params[:location_id])
    respond_to do |format|
      format.json { render :json => @courses }
    end
  end 
  def course_search
    if params[:location].present? && params[:location].strip != ""
      @courses = Course.where("location_id = ?", params[:location])
    else
      @courses = Course.all
    end
  end

end

Step -3. Create a js file for populating the courses dropdown list with changes the location dropdown.

# app/assets/javascripts/courses.js

$(function() {

   if ($("select#location").val() == "") {
    $("select#course option").remove();
    var row = "<option value=\"" + "" + "\">" + "Course" + "</option>";
    $(row).appendTo("select#course");
   }
   $("select#location").change(function() {
    var id_value_string = $(this).val();
    if (id_value_string == "") {
     $("select#course option").remove();
     var row = "<option value=\"" + "" + "\">" + "Course" + "</option>";
     $(row).appendTo("select#course");
    } else {
     // Send the request and update course dropdown
     $.ajax({
      dataType: "json",
      cache: false,
      url: '/get_courses_by_location/' + id_value_string,
      timeout: 5000,
      error: function(XMLHttpRequest, errorTextStatus, error) {
       alert("Failed to submit : " + errorTextStatus + " ;" + error);
      },
      success: function(data) {
       // Clear all options from course select
       $("select#course option").remove();
       //put in a empty default line
       var row = "<option value=\"" + "" + "\">" + "Course" + "</option>";
       $(row).appendTo("select#course");
       // Fill course select
       $.each(data, function(i, j) {
        row = "<option value=\"" + j.id + "\">" + j.title + "</option>";
        $(row).appendTo("select#course");
       });
      }
     });
    }
   });

  });

Step - 4. Now add the courses js to application.js file bellow the jquery file.

# app/assets/javascripts/application.js

//= require jquery
//= require jquery_ujs
//= require courses
//= require_tree .

Step - 5. Here the course search form

# app/views/courses/course_search.html.erb

<div class="row no-gutters wow slideInUp" data-wow-duration="1s">
  <div class="col-md-12 home-form">
    <%= form_tag(course_search_path, method: "get", class: "form-inline", remote: true) do %>
    <%= select_tag "location", options_from_collection_for_select(Location.all, "id", "header"), prompt: "Location", class: "custom-select mb-0 mr-sm-0 mb-sm-0" %>
    <%= select_tag "course_type", options_from_collection_for_select(Course.all, "id", "course_type"), prompt: "Course Type", class: "custom-select mb-0 mr-sm-0 mb-sm-0" %>
    <%= select_tag "course", options_from_collection_for_select(Course.all, "id", "title"), prompt: "Course", class: "custom-select mb-0 mr-sm-0 mb-sm-0" %>
    <%= submit_tag("Search", class: "btn btn-primary") %>
<% end %>
  </div>
</div>

<div class="row" id="course_listing">
  <%= render partial: "course_list", locals: {courses: @courses} %>
</div>

Step - 6. Now you have to create a course_list partial file to display all courses

# app/views/courses/_course_list.html.erb
<% courses.each do |course| %>
  <%= course.id %>
  <%= course.title %>
  <hr />
<% end %>

Step - 7. Create a js view file for display courses for ajax search form submit.

# app/views/courses/course_search.js.erb
$('#course_listing').html('<%= j render partial: "course_list", locals: {courses: @courses} %>')

I hope it should work.

Rubefaction answered 27/1, 2018 at 8:43 Comment(8)
Hi @sahidur, So i've tried that and it does give results in the url such as localhost:3000/?location=10&course_type=21&course=22 The result i'm looking for is that when I select a location in the first search form then the courses column will only show courses that are in that location in the that section of the form. Then when the user hits submit they will be brought to the show page of the course they are left with. Does that make sense?Bronchiectasis
Hi @Bradley, I modified the answer. Now After change the search form location dropdown then trigger ajax and change the course dropdown list and then if user hit the search button then change the course list with adding remote:true on search form. Hope it works and fulfill your requirement. Happy coding.Rubefaction
I'll check this now Sahidur. If it works I'll owe ya a drink. Thank you.Bronchiectasis
Spot on Sahidur. Thanks a million!Bronchiectasis
One quick point Sahidur. If I want to now make the search bar go to the course highlighted in the form how to select the course_id to include in a link_to because the form code seems to just pull all the available courses associated to the location. Is there a way to get the id for the current selected course in the form? <%= link_to 'View Course', course_path(), class: "btn btn-primary" %>Bronchiectasis
Hi @Bradley, You can add a course show link with modify from app/views/courses/_course_list.html.erb file, e.g - <%= link_to "Show", course_path(course) %>. Make sure your project have a course show action.Rubefaction
Yeah I noticed I could do that but I'd rather not have a course_list partial. I'd prefer if the user could just use the submit button to view the course that's left after they select the location and one of the courses from the Course.all list that relates to that location. This would be ideal for me instead of having a list underneath the search bar. Its more of a quick select button from a list of courses that relates to the location they choose.Bronchiectasis
I'm unsure how to get the course id value from the ajax response? the course id is in the html <option value="2"> value. How can I grab that into the button to use in the course_path() pleaseBronchiectasis

© 2022 - 2024 — McMap. All rights reserved.