Sumeet Masih
Sumeet Masih

Reputation: 607

Dynamic Select Menu in Ruby on Rails

Thanks in advance for whoever tries or answer my issue. I have City Model, Area model, User model. City Model and Area Model has "has_many" association where as Area Model and User Model has "has many through" association

I want Area select menu to display According to City selected, While creating a new user when any item in city select menu is selected (ajax request is made), area select menu should show areas that belongs to that city.

This is my code please tell me where M i wrong. (Thanks)

(app/views/users/_form)
<%= form_for(@user, remote: true) do |f| %>
  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
<p>
<%=f.collection_select :city_id, City.order(:name), :id, :name, include_blank: true%>
</p>

<div class="a"></div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

(app/controllers/users_controller.rb)

    class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

    def custom
        @tilu = params[:city_id]
      respond_to do |format|
        format.js
      end
    end
  # GET /users
  # GET /users.json
  def index
    @users = User.all
  end

  # GET /users/1
  # GET /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = User.new
    @areas= Area.all
  end

  # GET /users/1/edit
  def edit
  end

  # POST /users
  # POST /users.json
    before_action :get_area, only:[:create]
  def create
    @user = User.new(user_params)

      @user.area_ids = @area

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /users/1
  # PATCH/PUT /users/1.json
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.json
  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end
    def get_area
        @area = params[:user][:area_id]
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def user_params
        params.require(:user).permit(:name, :description,[:area_id])
    end
end

(app/assets/javascripts/users.js.coffe)

jQuery ->
  $(document).on 'change', '#user_city_id', (evt) ->
    $.ajax '/users/custom',
      type: 'GET'
      dataType: 'html'
      data: {
        city_id: $('#user_city_id :selected').val()
      }
      error: (jqXHR, textStatus, errorThrown) ->
        console.log("AJAX Error: #{textStatus}")
      success: (data, textStatus, jqXHR) ->
        console.log("Dynamic country select OK!")

(config/routes.rb)

Rails.application.routes.draw do
  resources :users
  resources :areas
  resources :cities
    get 'users/custom'

(app/views/users/_customTemplate.html.erb)

<%=f.collection_select :area_id, Area.where(city_id: @tilu), :id, :name, include_blank: true %>

last but not the least... (app/views/users/custom.js.erb)

$('.a').append("<%=j render 'customTemplate' %>");

help!!

ruby server console error

Started GET "/users/custom?city_id=1" for 127.0.0.1 at 2015-09-30 21:20:01 +0530 Processing by UsersController#show as HTML
Parameters: {"city_id"=>"1", "id"=>"custom"} User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 0]] Completed 404 Not Found in 76ms (ActiveRecord: 0.3ms)

ActiveRecord::RecordNotFound (Couldn't find User with 'id'=custom):
app/controllers/users_controller.rb:77:in `set_user'

Rendered /usr/local/lib/ruby/gems/2.2.0/gems/actionpack-4.2.1/lib/action_dispatch/middleware/templates/rescues/_source.erb (4.1ms)

Browser console error

GET http://localhost:3000/users/custom?city_id=1 404 (Not Found)send @ jquery-4075e3b7b3964707c653f61b66f46dec.js?body=1:9665jQuery.extend.ajax @ jquery-4075e3b7b3964707c653f61b66f46dec.js?body=1:9216(anonymous function) @ users-c743c610a872f962fb75a7ac244905cd.js?body=1:4jQuery.event.dispatch @ jquery-4075e3b7b3964707c653f61b66f46dec.js?body=1:4671elemData.handle @ jquery-4075e3b7b3964707c653f61b66f46dec.js?body=1:4339ListPicker._handleMouseUp @ about:blank:544 users-c743c610a872f962fb75a7ac244905cd.js?body=1:11 AJAX Error: error

Upvotes: 3

Views: 5579

Answers (2)

Sumeet Masih
Sumeet Masih

Reputation: 607

this example worked for me.. however I had to convert my colection_select to just select but never the less its working and Thanks to all those who tried to resolve the issue

[1]: https://kernelgarden.wordpress.com/2014/02/26/dynamic-select-boxes-in-rails-4/

Upvotes: 0

Richard Peck
Richard Peck

Reputation: 76774

Ok there are too many issues for me to pick through them; this is what I'd do:


You're looking for something called dynamic select menus. You mention this in the title, I just wanted to clarify the terminology.

Dynamic select menus should send an ajax request when you change the value in the select box. The process should be succinct (IE you only send an ID to your controller), and you end up with a set of returned data to populate the next select box:

#config/routes.rb
resources :cities do
    get "update", to: "users#custom" #-> url.com/cities/:city_id/update
end
resources :users #-> put this below so that the users/show method doesn't catch the above calls

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   def custom
      @city = City.find params[:city_id]
      respond_to do |format|
        format.js
      end
   end
end

#app/views/users/custom.coffee
$('.a').append("<%=j render 'users/customTemplate' %>");

Above is the "backend". Here is the "Frontend":

#app/views/users/_form.html.erb (removed HTML to clean it up for this)
<%= form_for(@user, remote: true) do |f| %>
    <%= f.text_field :name %>
    <%= f.collection_select :city_id, City.order(:name), :id, :name, include_blank: true %>
    <%= f.submit %>
<% end %>

#app/assets/javascripts/users.coffee
$(document).on 'change', '#user_city_id', (evt) ->
    $.ajax '/cities/' + $(this).val() + '/update',
      type: 'GET'
      dataType: 'html'
      data: {
        city_id: $('#user_city_id :selected').val()
      }
      error: (jqXHR, textStatus, errorThrown) ->
        console.log("AJAX Error: #{textStatus}")
      success: (data, textStatus, jqXHR) ->
        console.log("Dynamic country select OK!")

You'll gain a lot from watching this Railscast:

enter image description here

Upvotes: 3

Related Questions