Is there a way to filter a dropdown list based on another dropdown's value ?
For example, if we have: Class and Student Models where Student have class_id; is there a way to filter the Students shown in the dropdown based on the selected Class ?
EDIT
Apparently, rails_admin gem has an association relationship which I was looking for; but it doesn't work perfectly.
Given two <select> elements "Class" and "Student", with the Student list containing data-class_id attributes referencing values from the Class list (see snippet below), you can filter the "Student" dropdown based on the "Class" dropdown's value using the following vanilla-JavaScript code:
var firstSelectId = "Class";
var secondSelectId = "Student";
var data_attr = "class_id";
this.addEventListener("DOMContentLoaded", function(event) {
var firstSelect = document.getElementById(firstSelectId);
var secondSelect = document.getElementById(secondSelectId);
firstSelect.addEventListener("change", function(event) {
var value = event.target.value;
Array.prototype.forEach.call(secondSelect.options, function(item) {
item.style.display = (item.dataset[data_attr] === value) ? 'inline' : 'none';
});
var selected = secondSelect.selectedOptions[0];
if (selected && selected.dataset[data_attr] !== event.target.value) {
secondSelect.selectedIndex = -1;
}
});
firstSelect.dispatchEvent(new Event('change'));
});
<form id="myform">
Select a class and student:
<select id="Class">
<option value="1">Class1</option>
<option value="2">Class2</option>
<option value="3">Class3</option>
</select>
<select id="Student">
<option value="StudentA" data-class_id="1">A</option>
<option value="StudentB" data-class_id="2">B</option>
<option value="StudentC" data-class_id="3">C</option>
<option value="StudentD" data-class_id="2">D</option>
<option value="StudentE" data-class_id="1">E</option>
<option value="StudentF" data-class_id="1">F</option>
</select>
</form>
If you can use Javascript, this Railscast will help you:
In this instance, your dropdowns may look like this:
<%= f.collection_select :class_id, Class.all, :id, :name, {:prompt => "Select a Class"}, {:id => "class"} %>
<%= f.collection_select :student_id, Student.all, :id, :name, {:prompt => "Select a Student"}, {:id => "student"} %>
And you would use Javascript to change the options in the Student dropdown. You can get the value of the class using:
class_id = $("#class").find(":selected").text()
This is the related link: https://github.com/sferik/rails_admin/wiki/Associations-scoping which edited the origin question
Related
i have static hash :
STATUS_BRAND = {
active: "hoatdong",
deactive: "khonghoatdong",
}.freeze
my view:
= f.select :status, Brand::STATUS_BRAND, class: "form-control post-type input-bg"
i wanto display value in here is : "hoatdong" and "khonghotdong" in views
If you do not want the select to return the keys to Rails, then you have to invert the Hash:
f.select(:status, options_for_select(Brand::STATUS_BRAND.invert), ...)
Output:
<option value="active">hoatdong</option>
<option value="deactive">khonghoatdong</option>
You can look at the documentation for options_for_select for more examples.
= form_tag questions_path, :method=>:post do
= label :question, :type, 'Type: '
= select :question, :type, %w(Text Picture Audio Video), :id=> :question_type_combo
**- if :question_type_combo.selected != 'Text'**
= label :question,:url, 'URL: '
= text_field :question,:url, :id=> :question_url_text
= submit_tag 'Add Question',:id=>:add_question_button
Is something of this sort possible in HAML? I wish to render the textfield only for certain options if selected in the SELECT BOX above.
Yes and no. You can write a conditional based on the values of the record that you bind to the form:
= form_for #question do |f|
= f.label :type
= f.select, :type, %w(Text Picture Audio Video), id: 'question_type_combo'
- unless f.object.question_type_combo === 'Text'
= f.label :url
= text_field :url, id: 'question_url_text'
But this would only change the visibility after the user submits the form and not be very useful.
Instead you can just use jQuery to create an event handler for the ´change´ event.
$(document).on('change','#question_type_combo', function(){
var type = $(this).first(':selected').val();
var $other_input = $('#other_input');
if (type == 'Text') {
$other_input.hide();
} else {
$other_input.show();
}
});
// sets the initial state
// if you are using turbolinks
$(document).on('page:load', function(){
$('#question_type_combo').trigger('change');
});
// if you are not using turbolinks
$(function(){
$('#question_type_combo').trigger('change');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<div class="field">
<label>Type</label>
<select name="question[question_type_combo]" id="question_type_combo">
<option>Text</option>
<option>Something else</option>
</select>
</div>
<div class="field" id="other_input">
<label>URL</label>
<input type="text" name="question[url]">
</div>
</form>
- if :question_type_combo.selected != 'Text' This is not possible in the haml view, If you want to do something based on selected option you have to use js.
Or you may set the selected option using similar code if you have controller objects:
= select_tag("fee_discount", options_for_select(Fee.discounts.keys.map {|k| [k.titleize, k]}, selected: "#{"rewards" if #vendor.present? && #vendor.approved?}"), include_blank: true)
Or
You may keep the label and text_field inside a div with hide class.
And then using javascript you may hide unhide the div.
I have a mix of ruby rails code
I have a form with a selection option that i want to be a required, and i want to validate. If user do not select anything i want to validade with a error message.
However, I try to copy past code from internet, I'm new at ruby rails and I still not have a error message.
I also check that i use 'required' , or if i use 'validates_presence_of' doesn't make difference because it's a submit form (i think)
test_filteR_form.rb
class TestFilterForm < ApplicationForm
attribute :model, String
validates_presence_of :model
end
.html.erb
<%= f.input :fill_form_error_message,:as => :hidden, :input_html => { :value =>I18n.t('test.fill_form_error') } %>
<%= f.input :model, label: I18n.t('test.filters.model'), autofocus: true, input_html: {class: 'input-xlarge chosen-select' }, collection: TestType.options_for_select, include_blank: true %>
"/>
controller
def paginate
#test_form = TestForm.new(params)
unless #test_form.valid?
#model = params[:test_filter_form][:model]
#h_model = #model.pluralize + 'H'
#history, _query, #test_fields = TestQueryService.search!(params)
session[:test_query] = _query
session[:test_klass] = #model
else
format.json { render :json => { :error => #test_form.errors.full_messages }, :status => 422 }
end
js.coffee
$contentDiv.on 'ajax:error', 'form[data-value]', (event, xhr, status, error) ->
data = $.parseJSON(xhr.responseText)
$result = $(#).parents('tr').find('[data-result]')
controller.resultUpdateError xhr.status, $result.data('result'), data, $(#)
# Hide row loading spinner
$(#).parents('tr').find('span[role="result_update_spinner"]').hide()
# Hide saved form
$(#).parents('tr').find('.saved_form').hide()
resultUpdated: (result, data, $form) ->
if data.flash != undefined
# Sets a sucess message on page top
flash data.flash.type, data.flash.message
# Sets a success message on row
$fieldForm = $form.parents('tr').find(".messages")
$fieldForm.find('.controls').empty()
$fieldForm.find('.control-group .controls').css('color', 'green').append #_inlineMessage("Gravado com sucesso")
# Hide success message after some time
setTimeout ((self) ->
->
$fieldForm.find('.control-group .controls').empty()
return
)(this), 4000
Since you are dynamically created the selection box then there must be a default value selected which is not nil so there is no change seen you can manually create selection like this:
<div class="form-group">
<%= f.label :select_user_country %><br/>
<select class="form-control select2" name="user[country_id]">
<option value="" selected disabled>Select a Country</option>
<%#countries.each do |country|%>
<option value="<%=country.id%>"><%=country.name%></option>
<%end%>
</select>
</div>
I have a select helper as seen below, I have disabled it and would like give "1" as default value, but couldnt find how?
<%= f.select :fuel_incl, [[t('shared.incl'),'1'],[t('shared.notInc'),'0']], {}, {class: "Select-control u-sizeFull fuel_incl", :disabled => true} %>
It is disabled so it should select 1 as default.
EDIT
I see that it works from the console;
<select class="Select-control u-sizeFull fuel_incl" disabled="disabled" name="boat[fuel_incl]" id="boat_fuel_incl">
<option selected="selected" value="1">Included</option>
<option value="0">Not Included</option></select>
but it does not send as params, when I take out disable true and select value send the form, it works..
EDIT2
anyways, I have solved it by giving only one select value as;
<%= f.select :fuel_incl,
[[t('shared.incl'),'1']],
{ selected: '1' },
{ class: "Select-control u-sizeFull fuel_incl" } %>
Add selected option:
<%= f.select :fuel_incl,
[[t('shared.incl'),'1'],[t('shared.notInc'),'0']],
{ selected: '1' },
{ class: "Select-control u-sizeFull fuel_incl", disabled: true } %>
I have this in my model:
LOCATION_IN_UK = {'England' => [['Berkshire', 1],['Cambridgeshire',2],['Cheshire',3]], 'Scotland' => [['Dumfries and Galloway',4],['Fife',5],['Lothian',6]], 'Others' => [['Outside UK',7]]}
And this is in the view:
<%= select_tag :location, grouped_options_for_select(Location::LOCATION_IN_UK), :id => 'location-dropdown' %>
This code generate following html:
<select id="location-dropdown" name="location">
<optgroup label="England">
<option value="1">Berkshire</option>
<option value="2">Cambridgeshire</option>
<option value="3">Cheshire</option></optgroup>
<optgroup label="Others">
<option value="7">Outside UK</option></optgroup>
<optgroup label="Scotland">
<option value="4">Dumfries and Galloway</option>
<option value="5">Fife</option>
<option value="6">Lothian</option></optgroup>
</select>
1. How to skip alphabetical sort order. I want elements locate exactly as in the hash LOCATION_IN_UK.
2. How to insert prompt into this? :prompt => 'Please select' Doesn't work
To answer your prompt question, prompt is not a hash, it is the third parameter of the method call. So you would do:
<%= select_tag :location, grouped_options_for_select(LOCATIONS_IN_UK, nil, "Please Select"), :id => 'location-dropdown' %>
And looking at the source code, it seems there is no way to skip the sorting. You could write your own helper method though. Here is the source
# File actionpack/lib/action_view/helpers/form_options_helper.rb, line 449
def grouped_options_for_select(grouped_options, selected_key = nil, prompt = nil)
body = ''
body << content_tag(:option, prompt, { :value => "" }, true) if prompt
grouped_options = grouped_options.sort if grouped_options.is_a?(Hash)
grouped_options.each do |group|
body << content_tag(:optgroup, options_for_select(group[1], selected_key), :label => group[0])
end
body.html_safe
end
You could modify/override that method, but that may break if you are using this function elsewhere, which is why I would suggest you put the following in your application_helper.
def unsorted_grouped_options_for_select(grouped_options, selected_key = nil, prompt = nil)
body = ''
body << content_tag(:option, prompt, { :value => "" }, true) if prompt
##Remove sort
#grouped_options = grouped_options.sort if grouped_options.is_a?(Hash)
grouped_options.each do |group|
body << content_tag(:optgroup, options_for_select(group[1], selected_key), :label => group[0])
end
body.html_safe
end
You can then call unsorted_grouped_options_for_select and it should work.
<%= select_tag :location, unsorted_grouped_options_for_select(LOCATION::LOCATION_IN_UK, nil, "Please Select"), :id => 'location-dropdown' %>
I had the same problem. You can solve this by using the array version instead of hashes since it only orders it if it is_a?(Hash).
See the docs for the format: http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/grouped_options_for_select