Reputation: 61
I have this coffeescript for dynamic select boxes to show only those models in models select box which relate to selected makes in makes select box. And I am gonna have multiple fields working with this function separately, so anonymous function wont work.
Coffeescripts looks like this
../assets/javascripts/diys.coffee
DynamicSelect = (makesSelect, modelsSelect) ->
$(document).on 'change', makesSelect, (evt) ->
$.ajax 'update_make_models',
type: 'GET'
dataType: 'script'
data: {
make_id: $("'makesSelect' option:selected").val()
}
error: (jqXHR, textStatus, errorThrown) ->
console.log("AJAX Error: #{textStatus}")
success: (data, textStatus, jqXHR) ->
console.log("Dynamic make select OK!")
../views/diys/update_make_models.coffee
$(modelsSelect).empty()
.append("<%= escape_javascript(render "make_models/make_model") %>")
And here's part of my form, which will repeat multiple times, only id's will change, which I will pass as arguments to "DynamicSelect" function. So where and what do I need to put to launch this function properly?
<div class="vehicle_field">
<%= f.fields_for :attached_vehicles do |av| %>
<p>Select make</p>
<%= av.select :make, options_for_select(@makes.collect { |m| [m.make_name, m.id] }), { include_blank: "Select make" }, { id: 'makes_select1' } %><br>
<p>Select model</p>
<%= av.select :model, (render "make_models/make_model"), {prompt: "Select model"}, { id: 'models_select1' } %><br>
<p>Select years</p>
<%= av.select :start_year, (Time.now.year + 1).downto(Time.now.year - 100).to_a, prompt: "Year (from)" %>
<%= av.select :end_year, (Time.now.year + 1).downto(Time.now.year - 100).to_a, prompt: "Year (to)" %><br>
<% end %>
</div>
------------------------------------------------------------------------------------------------------------------------------------ Edit, trying to accomplish dynamic select boxes with data-remote attribute as Richard Peck suggested
In console it seems that I'm getting right "make_id" in parameters when selecting make in makes select box, but I can't find the way to pass it to controllers @models variable, am I doing anything right?
Form part for selecting attached vehicles from view
<div class="vehicle_field">
<%= f.fields_for :attached_vehicles do |av| %>
<p>Select make</p>
<%= av.select :make, (@makes.collect { |m| [m.make_name, m.id] }), { include_blank: "Select make" }, { data: { remote: true, url: "update_make_models", name: "make", update: "#diy_attached_vehicles_attributes_0_model"} } %><br>
<p>Select model</p>
<%= av.collection_select :model, @models, (render "make_models/make_model"), {prompt: "Select model"} %><br>
<p>Select years</p>
<%= av.select :start_year, (Time.now.year + 1).downto(Time.now.year - 100).to_a, prompt: "Year (from)" %>
<%= av.select :end_year, (Time.now.year + 1).downto(Time.now.year - 100).to_a, prompt: "Year (to)" %><br>
<% end %>
</div>
_make_model.html.erb partial
<% @models.collect do |models| %>
<option value="<%= models.id %>"><%= models.make_model_name %></option>
<% end %>
New action in diys_controller
def new
@diy = Diy.new
@step = @diy.steps.new
@attached_vehicle = @diy.attached_vehicles.new
@step.add_images_to_steps.new
@makes = Make.all
@models = MakeModel.where("make_id = ?", params[:make])
end
Also removed both coffeescripts and edited routes
get '/diys/update_make_models', to: 'diys#new', as: 'update_make_models'
And this is what I'm getting in console after selecting make
Started GET "/diys/update_make_models?diy%5Battached_vehicles_attributes%5D%5B0%5D%5Bmake%5D=12" for ::1 at 2016-02-17 20:03:21 +0200
Processing by DiysController#new as JS
Parameters: {"diy"=>{"attached_vehicles_attributes"=>{"0"=>{"make"=>"12"}}}}
Make Load (1.0ms) SELECT "makes".* FROM "makes"
MakeModel Load (1.0ms) SELECT "make_models".* FROM "make_models" WHERE (make_id = NULL)
Rendered make_models/_make_model.html.erb (3.0ms)
Rendered diys/_form.html.erb (151.0ms)
Rendered diys/new.html.erb within layouts/application (260.0ms)
Completed 200 OK in 451ms (Views: 446.4ms | ActiveRecord: 2.0ms | Solr: 0.0ms)
Upvotes: 1
Views: 504
Reputation: 76774
You can just bind .on
to the element itself:
#app/assets/javascripts/application.coffee
$(document).on "change", "select#makes_select1", (evt) ->
$.ajax 'update_make_models',
type: 'GET'
dataType: 'script'
data:
make_id: $(this).find("option:selected").val()
error: (jqXHR, textStatus, errorThrown) ->
console.log "AJAX Error: #{textStatus}"
success: (data, textStatus, jqXHR) ->
console.log "Dynamic make select OK!"
Something cool you'll want to look at is the data-remote
attribute for select
boxes:
= f.collection_select :attribute, @collection, :id, :name, {}, { data: {remote: true, url: "update_make_models"} }
This passes the variable params[:object][:attribute]
to the data-url
, which you'll be able to mange in your controller to pull back the required data you want.
Using the above code will rid you of the need for the ajax
definition in your JS.
Upvotes: 1