PLease help , I used some examples to build dynamic select, but it does not seem to work , nevertheless in console I can see 200 status, I am not fluent so please please help, The problem is that list in the select will not decrease, it shows same options after choosing previos
index.html.erb
<%= collection_select(nil, :site_id, #sites, :id, :name, {:prompt => "Select a Site"}, { :id => "sites_select"}) %>
<br/>
<%= collection_select(nil, :floor_id, #floors, :id, :name, {:prompt => "Select a Floor"}, {:id => "floors_select"}) %>
<br/>
<%= collection_select(nil, :pod_id, #pods, :id, :name, {:prompt => "Select a pod"}, {:id => "pods_select"}) %>
<script>
$(document).ready(function() {
$('#sites_select').change(function() {
$.ajax({
url: "<%= update_floors_path %>",
data: {
site_id : $('#sites_select').val()
},
dataType: "script"
});
});
$('#floors_select').change(function() {
$.ajax({
url: "<%= update_pods_path %>",
data: {
floor_id : $('#floors_select').val()
},
dataType: "script"
});
});
});
</script>
devices_controller.rb
def update_floors
# updates floors and pods based on genre selected
site = Site.find(params[:site_id])
# map to name and id for use in our options_for_select
#floors = site.floors.map{|a| [a.name, a.id]}.insert(0, "Select a Floor")
#pods = site.pods.map{|s| [s.name, s.id]}.insert(0, "Select a Pod")
end
def update_pods
# updates pods based on floor selected
floor = Floor.find(params[:floor_id])
#pods =floor.pods.map{|s| [s.name, s.id]}.insert(0, "Select a Pod")
end
update_floors.js.erb
$('#floors_select').html("<%= escape_javascript(options_for_select(#floors)) %>");
$('#pods_select').html("<%= escape_javascript(options_for_select(#pods)) %>");
update_pods.js.erb
$('#pods_select').html("<%= escape_javascript(options_for_select(#pods)) %>");
routes.rb
get 'devices/update_floors', :as => 'update_floors'
get 'devices/update_pods', :as => 'update_pods'
root :to => "devices#index"
Appreciate any suggestion
Thank you,
D
Seems new loaded JavaScript not adding effects to parent page. Why not do the $().html inside the Ajax success callback. And make the update.js.html page only contains the options for select. Should work.
javascript:
$("#sites_select").change(function(){
$.ajax({
url: your_url,
//orther options ...
success: function(data){
$("#floors_select").html(data);
}
});
});
and in your update_floors.js.html
<%=options_for_select(#floors)%>
Do the same for update pods. :)
Problem is with your controller,
You have not mentioned the respond_to js block any where in the code,
Just put this code in both update methods,
respond_to do |format|
format.js
end
Give the response format in the controller respond_to :js, :only=>[:update_floors,:update_pods ]
Apart from that write the following into update_floors.js.erb file.
$('#floors_select').html("<%= escape_javascript(collection_select(:your_object_name, :floor_id, #floors.to_a, :id, :name, :prompt=>"Select a Floor")) %>");
I think the above will work.
Related
I'm working on a Rails 6 app, and want to update page view based on a dropdown value selected using XHR. Dropdown must use GET method coz I am calling index action.
I am using form_with which by default uses remote: true.
I am not using local: true.
I tried onchange: "Rails.fire(this.form, 'submit')" - this does send XHR request and receives a response but does not update view.
I tried onchange: "this.form.submit();" - this does a full page reload not utilizing XHR.
Code from app/views/users/index.html.erb
<%= form_with url: station_users_path(station_id: Current.user.home_station), method: :get do |form| %>
<%= form.select :user_status, options_for_select( { "Active users" => "unlocked", "Inactive users" => "locked"}, #user_status ), {}, { :onchange => "Rails.fire(this.form, 'submit')" } %>
<% end %>
Code from app/controllers/users_controller.rb
def index
#user_status = params[:user_status] || "unlocked"
#users = #station.users.send(#user_status) || []
#user_status == "unlocked" ? seperate_managers_from_users : #managers = []
end
In onchange just write one get_station_users() function. Inside that you can use ajax calling.
In forms
<%= form_with url: station_users_path(station_id: Current.user.home_station), id: “form_id”, method: :get do |form| %>
<%= form.select :user_status, options_for_select( { "Active users" => "unlocked", "Inactive users" => "locked"}, #user_status ), {}, { :onchange => "get_station_users()" } %>
<% end %>
Add Script
function get_station_users(){
$.ajax({
type: "GET",
url: "/station_users",
data: { $('#form_id').serialize(), },
dataType: 'script'
});
}
Your response will be as JS. So you can use index.js.erb
Hey guys im currently working on a devise sign up form, the end goal is a user can select a state from the united states and a select tag below will populate with the correct cities in that state. im using the city-state gem. https://github.com/loureirorg/city-state
ive looked at other examples like this one https://forum.upcase.com/t/dependent-country-city-state/7038 my code is below
routes.rb
resources :states, only: :new
registrations.new.html.erb
<div class="field">
<%= f.select :state, options_for_select(CS.states(:us)), {:prompt => "State"}, {:class => "signup-input-container--input", :id => "state-picker"} %>
</div>
<div class="field">
<%= f.select :city, options_for_select([]),{}, {:class => "signup-input-container--input", :id => "city-picker"} %>
</div>
main.js
document.addEventListener("turbolinks:load", function(){
var state = document.getElementById("state-picker");
state.addEventListener("change", function() {
Rails.ajax({
url: "/states?country=" + "United States" + "&state=" +
state.value,
type: "GET"
})
})
});
registrations-controller.erb
def new
super
#cities = CS.get(:us, params[:state])
end
new.js.erb
var city = document.getElementById("city-picker");
while (city.firstChild) city.removeChild(city.firstChild);
var placeholder = document.createElement("option");
placeholder.text = "Choose a city";
placeholder.value = "";
city.appendChild(placeholder);
<% #cities.each do |c| %>
city.options[city.options.length] = new Option('<%= c %>');
<% end %>
im trying to get this to work the way the example link shows. the only difference is that users will only choose states from the US and citys
From our discussion in the comments the issue appears to be that you are requesting the wrong URL for your cities.
You have a route at /states/new but are making the request to /states. Try updating your main.js to:
document.addEventListener("turbolinks:load", function(){
var state = document.getElementById("state-picker");
state.addEventListener("change", function() {
Rails.ajax({
url: "/states/new?state=" + state.value,
type: "GET"
})
})
});
(I removed the country parameter in the URL because you don't seem to be using it, you say you only need this for the US anyway.)
Let me know how you get on with that.
I need in my app to select from a list of provider a provider, and then, via ajax, I could see below a list of categories, that belongs to a specific provider. I have a form in activeadmin:
<%= semantic_form_for [:admin, #game], builder: ActiveAdmin::FormBuilder do |f| %>
<%= f.semantic_errors :state %>
<%= f.inputs do %>
<%= f.input :categorization_id, label: 'Provider', as: :select,
collection: Provider.all.map { |provider| ["#{provider.name}", provider.id] },
input_html: { class: (:provider_select), 'data-url': category_select_path(provider: 4) } %>
<%= f.input :categorization_id, label: 'Category',input_html: { class: ('category_dropdown') }, as: :select,
collection: Category.all.map { |category| ["#{category.name}", category.id]}%>
...
<% end %>
<%= f.actions %>
<% end %>
In activeadmin controller I have:
controller do
def ajax_call
#provider = Provider.find(params[:provider])
#categories = #provider.categories
respond_to do |format|
format.json { render json: #categories }
end
end
end
JS:
$(document).on('ready page:load', function () {
$('.select.input.optional').last().addClass('hidden_row');
$('#game_categorization_id').change(function () {
var id_value = this.value;
$('.hidden_row').removeClass('hidden_row');
$.ajax({
type: 'GET',
url: '/admin/games/category_select'
// data: id_value
})
});
});
And the routes: match '/admin/games/category_select' => 'admin/games#ajax_call', via: :get, as: 'category_select'
I don't have an idea, how can I pass providers id from collection into url. Currently, I have there category_select_path(provider: 4), but actually it has to be smth. like this - category_select_path(provider: provider.id) In the browser, in a Network tab of devtools I can see my category_select, but there is an error: Couldn't find Game with 'id'=category_select. I can't figure out from where does it come. Any suggestions? Thanks.
The problem was in routes: match '/admin/games/category_select' => 'admin/games#ajax_call', via: :get, as: 'category_select'. It is reserved by a show action of Activeadmin controller. So I changed my routes to: get '/admin/select_category' => 'admin/games#get_providers_categories', as: 'select_category', and added to ajax call data: {provider: provider}, so I could fire in params id of provider:
$.ajax({
type: 'GET',
url: '/admin/select_category',
data: {
provider: provider
},
success: (function (data) {
$('#select_category').children('option').remove();
$('#select_category').prepend('<option value=""></option>');
$.each(data.categories, function () {
$('#select_category').append('<option value="' + this.id + '">' + this.name + '</option>')
})
})
})
How can I use simple_form to filter a field, based on a previous fields value?
For instance, I have an Opportunities form, with two fields, Company and Contact.
Company Field:
<div class="form-group">
<%= f.association :company, collection: Company.all.order(:account), prompt: "", :label_method => :account, :value_method => :id %>
</div>
Contact Field:
<div class="form-group">
<%= f.association :contact, collection: Contact.all.order(:first_name), prompt: "", :label_method => lambda { |contact| "#{contact.first_name} #{contact.last_name}" }, :value_method => :id %>
</div>
Here is what I want to do: If I select a company called "Deviant" from the Company field above, I want the Contact field to only display those contacts associated with the company called "Deviant".
I am trying something like this, but can't get it to work:
<div class="form-group">
<%= f.association :contact, collection: Contact.where("company_id = ?", params[:id]), prompt: "", :label_method => lambda { |contact| "#{contact.first_name} #{contact.last_name}" }, :value_method => :id %>
</div>
I don't know how to reference the value in the Company field.
How can I do this?
Thanks.
Update
Anyone? Surely this must be possible. This is a key functionality in any form. I would hope I don't need jQuery or something.
I think the best approach is to use ajax requests to update your contacts collection dinamically whenever the company's selected value is changed.
First you'll need an action in your contacts controller:
app/controllers/contacts_controller.rb
class ContactsController < ApplicationController
def contacts_list
if params[:company_id]
#contacts = Contact.where(company_id: params[:company_id])
else
#contacts = Contact.all
end
respond_with(#contacts) do |format|
format.json { render :json => #contacts.to_json(:only => [:id, :first_name, :last_name]) }
end
end
end
Add this to your routes:
config/routes.rb
post 'contacts_list' => "contacts#contacts_list", as: :contacts_list
Then use the coffeescript code bellow to populate your contacts' collection:
app/assets/javasctipts/companies.js.coffee
$(document).ready ->
if $("#opportunity_company_id")
populate_contacts()
$("#opportunity_company_id").change ->
populate_contacts()
populate_contacts = ->
$contacts_select = $("select#opportunity_contact_id")
$contacts_select.attr "disabled", "disabled"
company_id = $("select#opportunity_company_id").val()
if company_id is ""
$contacts_select.html "<option value=\"\">(select the company first)</option>"
else
$contacts_select.html "<option value=\"\">(loading contacts...)</option>"
data = {company_id: company_id}
data[window._auth_token_name] = window._auth_token
$.ajax "/contacts_list",
type: "post"
dataType: "json"
data: data
success: (contacts) ->
_html = '<option value="">Select the contact:</option>'
_html += '<option value="'+contact.id+'">'+contact.first_name + ' ' + contact.last_name + '</option>' for contact in contacts
$contacts_select.html _html
$contacts_select.removeAttr "disabled"
error: ->
alert 'Error trying to load contacts.'
Finally, inside your html's head tag:
<% if protect_against_forgery? %>
<script>
window._auth_token_name = "<%= request_forgery_protection_token %>";
window._auth_token = "<%= form_authenticity_token %>";
</script>
<% end %>
Hope it helps...
update:
Add the following line to your ApplicationController (app/controllers/application_controller.rb):
respond_to :html, :xml, :json, :js
I have two drop down boxes in my application.
Based on the value selected in 1st combobox, the values in 2nd drop down box should be populated.And these values should come from Database.
Please help me.
here's a clean approach using jquery-ujs (https://github.com/rails/jquery-ujs)
In your view:
<%=
select_tag
:first_select, # name of selectbox
options_from_collection_for_select(#myrecords, "id", "name"), # your options for this select box
:'data-remote' => 'true', # important for UJS
:'data-url' => url_for(:controller => 'MyController', :action => 'getdata'), # we get the data from here!
:'data-type' => 'json' # tell jQuery to parse the response as JSON!
%>
<%=
select_tag
:second_select, # name of selectbox
"<option>Please select something from first select!</option>"
%>
Your Controller:
class MyController < ApplicationController
def getdata
# this contains what has been selected in the first select box
#data_from_select1 = params[:first_select]
# we get the data for selectbox 2
#data_for_select2 = MyModel.where(:some_id => #data_from_select1).all
# render an array in JSON containing arrays like:
# [[:id1, :name1], [:id2, :name2]]
render :json => #data_for_select2.map{|c| [c.id, c.name]}
end
end
In your application.js:
$(document).ready(function() {
// #first_select is the id of our first select box, if the ajax request has been successful,
// an ajax:success event is triggered.
$('#first_select').live('ajax:success', function(evt, data, status, xhr) {
// get second selectbox by its id
var selectbox2 = $('#second_select');
// empty it
selectbox2.empty();
// we got a JSON array in data, iterate through it
$.each(data, function(index, value) {
// append an option
var opt = $('<option/>');
// value is an array: [:id, :name]
opt.attr('value', value[0]);
// set text
opt.text(value[1]);
// append to select
opt.appendTo(selectbox2);
});
});
});
You could take inspiration from what I have in a project of mine. It updates the state given the country selected.
It makes use of Carmen a great gem listing countries, states etc...
View:
<p>
<label>Country <span>*</span></label>
<%= profile_form.select(:country,Carmen.countries, {:include_blank => 'Select a Country'}, :id => "profile_country") %>
</p>
<p>
<label>State <span>*</span></label>
<%= profile_form.select(:state, "" , {:include_blank => 'Select a Country first'}, :id => "profile_state") %>
</p>
Jquery code:
$('#profile_country').change(function() {
if ($(this).val() == '')
{
$('#profile_state').html( $('<option>No state provided for your country</option>'));
}
else {
$.ajax({
type: "GET",
url: "/remote/get_states/" + encodeURIComponent($(this).attr('value')),
success: function(data){
if (data.content == 'None') //handle the case where no state related to country selected
{
$('#profile_state').empty();
$('#profile_state').append( $('<option>No state provided for your country</option>'));
}
else
{
$('#profile_state').empty();
$('#profile_state').append( $('<option>Select your State</option>'));
jQuery.each(data,function(i, v) {
$('#profile_state').append( $('<option value="'+ data[i][1] +'">'+data[i][0] +'</option>'));
});
}
}
});
}
});
Controller:
def states
begin
render :json => Carmen::states(CGI::unescape(params[:country]))
rescue
render :json => {"content" => "None"}.to_json
end
end
This is how I did it. Works in Rails 3.2
View:
<%= select_tag :major_category_select_id, options_from_collection_for_select(#majorcategories, 'id', 'name'), :'data-remote' => 'true', :'data-url' => url_for(:controller => 'listings', :action => 'submit_major_category', format: 'js') %>
Controller method:
def submit_major_category
#major_category = MajorCategory.find(params[:major_category_select_id])
#minor_categories = #major_category.minor_categories
respond_to do |format|
# format.html { render partial: 'minor_categories_select' }
format.js
end
end
Routes:
get "listings/submit_major_category"
Then create a submit_major_category.js.erb file that gets responded to.