How do you add onchange action to collection_select? - javascript

I have the following select drop down in my rails. I'm following the syntax from the API( http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select):
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
<%= collection_select(:sources, :source_id, Source.all, :id, :name, :include_blank => "Please select a source...", html_options = {:onchange => "updateTextArea()"} ) %>
function updateTextArea(){
alert('source changed')
}
I'm able to get the drop down to display just fine with the values from the DB when I don't include html_options. However, I'm stuck trying to get an onchange action to occur.

I think options needs to be in a hash (the part you have include_blank in currently). Try changing this
<%= collection_select(:sources, :source_id, Source.all, :id, :name, :include_blank => "Please select a source...", html_options = {:onchange => "updateTextArea()"} ) %>
to this
<%= collection_select(:sources, :source_id, Source.all, :id, :name, options = {include_blank: "Please select a source..."}, html_options = {:onchange => "updateTextArea()"} ) %>

I believe that in place of options = or html_options = you need to pass actual hash itself (like you actually did with include_blank => true). I would only explicitly mark those hashes with curly braces to separate them:
<%= collection_select(:sources, :source_id, Source.all, :id, :name, { :include_blank => "Please select a source..."}, {:onchange => "updateTextArea()"} ) %>
Hope this helps.
EDIT:
I forgot to add that if updateTextArea() JS function is not bind to a window there might be a problem with picking it up (I had similar problems in the past). For safety I would also do (if you are not using CoffeScript):
window.updateTextArea = function() { /* Your code */ }

Related

How do you pass in the value from collection_select to onchange function in Rails?

I'm trying to pass in the value selected from my collection_select drop down to an onchange function. When I do name, my value prints out as source[index], but I want the value of this not that as the text itself.
<%= collection_select(:source, :index, #sources, :id, :name, options = {include_blank: "Please select a source..."}, html_options = {:onchange => "updateTextArea(name)"}) %>
function updateTextArea(source){
var value = source;
console.log(value);
}
Try this:
html_options = {:onchange => "updateTextArea()"}
function updateTextArea() {
console.log($(this).val());
}
Changing the argument from "name" to "this.value" solved my problem.
<%= collection_select(:source, :index, #sources, :id, :name, options = {include_blank: "Please select a source..."}, html_options = {:onchange => "updateTextArea(this.value)"}) %>
function updateTextArea(source){
var value = source;
console.log(value);
}
I think it would be an example in below:
<%= f.collection_select(:id, index.sources, :id, :name,options = {include_blank: "Please select a source..."}, html_options = {:onchange => "updateTextArea(name)"}) %> #-> f is a form tag this you use this form
Hope will help you

How to Change Date Format According to User Selection?

How can I change the date :order according to the User's "f.select :categories" choice?
For example when a User goes to the Quantified _form he can select between "Monthly Average" or "One-Time Instance";
If he selects "Monthly Average" I want the _results_fields.html.erb to provide the date selection as ":order => [:month, :year]" if he selects "One-Time Instance" I want the _results_fields.html.erb to provide the date selection as ":order => [:month, :day, :year]
Ideally this would be done dynamically via javascript, but I would be happy to accept an answer that does it via the view.
_results_fields.html.erb
<div class="nested-fields">
<div class="form-group">
<%= f.text_field :result_value, class: 'form-control', placeholder: 'Enter Result' %>
<br/>
<%= f.date_select :date_value, :order => [:month, :year], class: 'date-select' %>
<%= link_to_remove_association "Remove Result", f %>
</div>
</div>
_form.html.erb
<%= form_for #quantified do |f| %>
<div class="america">
<%= f.select :categories, Quantified::CATEGORIES %>
<br/>
<br/>
<div class="form-group">
<%= f.text_field :name, class: 'form-control', placeholder: 'Enter Name' %>
</div>
<div class="form-group">
<%= f.text_field :metric, class: 'form-control', placeholder: 'Enter Metric' %>
</div>
<div id="results">
<%= f.fields_for :results do |result| %>
<%= render 'result_fields', :f => result %>
<% end %>
</div>
<div class="links">
<%= link_to_add_association 'add result', f, :results %>
</div>
<%= f.submit %>
</div>
<% end %>
quantified.rb
class Quantified < ActiveRecord::Base
belongs_to :user
scope :averaged, -> { where(categories: 'Monthly Average') }
scope :instance, -> { where(categories: 'One-Time Instance') }
has_many :results
accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true
CATEGORIES = ['Monthly Average', 'One-Time Instance']
end
Github: https://github.com/RallyWithGalli/ruletoday
Thank you for your time.
The answer here was to use some jquery provided by the gem that was being used to add the date selects, as well as some jquery of our own
First things first, we rig up the checkboxes with a click() event, that hides anything with the class 'day' if instance is checked, and shows it if not.
$('.date-toggle').click(function(){
if( $(this).attr('id') == 'instance') {
$('.day').show();
} else {
$('.day').hide();
}
});
The trick here is to use the rails date select option :with_css_classes on the date select, so that it looks like this:
<%= f.date_select :date_value, :order => [:month, :day, :year], :with_css_classes => true, class: 'date-select' %>
This causes each included field to get a class corresponding to its name, hence our reference to '.day' up there.
The next important part, however, because he is using a gem called cocoon to add new elements that included date fields, we had to use some of their jquery event bindings to make sure that the new ones got the right action applied to them.
$('#container').on('cocoon:after-insert', function(e, insertedItem) {
if($('#instance').is(':checked')) {
$('.day').show();
} else {
$('.day').hide();
}
});
Technically, the $('.day').show() is not necessary, because it defaults to being shown, but this, to me, gets across the intent a little clearer.
I think my solution is a little bit messy, but hopefully it gives you an indication of my train of thought and give you something to build upon.
I have changed your categories to work with a radio button group because the select field is a bit weird for 2 elements (subjective I know), to change it back to a select form,simply keep your code as is, but you will need to check the value of the select dropdown using jQuery .change() or some other vanilla Javascript way...
You haven't provided any controller names, so I didn't know how to name my JS file, but hopefully you know how to integrate.
IMO, I'm not sure why this needs AJAX, so maybe you can explain to me where that comes in.
_form.html.erb
<%= Quantified::CATEGORIES.each do |c| %>
<%= f.radio_button(:category, c) %>
<%= label(c, c) %>
<% end %>
_results_fields.html.erb
<%= f.date_select :date_value, :order => [:month, :year], class: 'date-select-my' %>
<%= f.date_select :date_value, :order => [:month, :year], class: 'date-select-mdy' %>
vanilla.js
$(document).ready(function(){
$('.date-select-mdy').hide();
$('.date-select-mdy').attr("disabled", true);
$('input[name$=\category\']').click(function() {
var target_value;
target_value = $(this).val;
if (target_value === 'Monthly Average') {
$('.date-select-my').show();
$('.date-select-mdy').hide();
$('.date-select-my').attr("disabled", false);
return $('.date-select-mdy').attr("disabled", true);
} else {
$('.date-select-my').hide();
$('.date-select-mdy').show();
$('.date-select-my').attr("disabled", true);
return $('.date-select-mdy').attr("disabled", false);
}
});
});
a_little_bit_of_coffee_because_i_dislike_js.coffee
$->
$('.date-select-mdy').hide()
$('.date-select-mdy').attr("disabled",true)
$('input[name$=\category\']').click ->
target_value = $(this).val
if target_value == 'Monthly Average'
$('.date-select-my').show()
$('.date-select-mdy').hide()
$('.date-select-my').attr("disabled",false)
$('.date-select-mdy').attr("disabled",true)
else
$('.date-select-my').hide()
$('.date-select-mdy').show()
$('.date-select-my').attr("disabled",true)
$('.date-select-mdy').attr("disabled",false)
return

Ajax for dynamic combo box selection in rails

I have two combo-box in single page. Now I want that If I select 1st combo-box option then in 2nd combo-box it automatically shows options related the 1st selected option without page refresh.
My Models:
class Location < ActiveRecord::Base
scope :active, -> { where(:is_active => true) }
has_many :stores
end
class Store < ActiveRecord::Base
scope :active, -> { where(:is_active => true) }
belongs_to :location
has_many :companies
end
class Company < ActiveRecord::Base
belongs_to :store
scope :active, -> { where(:is_active => true) }
end
In my HAML View Form
.field
.ui-widget
= f.label :location
= select_tag(:location, options_from_collection_for_select(Location.active, :id, :name), :prompt => "Select location")
.field
.ui-widget
= f.label :store
= f.select :store_id, Store.active.collect { |s| [s.name, s.id] }, :prompt => "Select store"
I know it is possible by using Ajax and I had also searched many ajax but it is for php and I can't understand how to use. I have never use Ajax before. Please help me.. Thanks in advance. :)
First of all understand one thing that AJAX is not related to php or rails, Its a javascript function call
now as per your question In my HAML View Form
.field
.ui-widget
= f.label :location
= select_tag(:location, options_from_collection_for_select(Location.active, :id, :name), :prompt => "Select location", onchange: "change_store(this)")
.field
.ui-widget#store_list
= f.label :store
= f.select :store_id, Store.active.collect { |s| [s.name, s.id] }, :prompt => "Select store"
now in js file
function change_store(select_tag){
value1 = $(select_tag).val()
$.ajax({
url: "controller_name/mehuod_name",
data: {data1: value1}
})
}
Now put route in route.rb file and create method in respective controller to find store list, then you can replace html under "select_lit" using jquery, simple
Hope this is what you are expecting

How to make Drop Down List, if model is created based on Single Table Inheritance on Ruby on Rails 4

I want to have form which shown fields based on the Type of Publications you select. I have used Single Table Inheritance (according to this [link] http://blog.thirst.co/post/14885390861/rails-single-table-inheritance) to create Publication model (base model), and subclasses (book_chapter, book_whole, conference_article, journal_article). Fields of Publications model are as follows: type, author, title, year, publication, volume, issue, page, keywords, abstract, publisher, placeofpublication, editor, seriestitle, seriesvolume, seriesissue, issn, isbn, area, url, doi.
So, based on the Type that will be chosen (for instance book_chapter), I want to have particular fields of Publications.
I handled to create dropdown list with types, but when select the type and create publications the Type record do not saved on database. This is the code for type dropdown
list
<%= f.label :type, :class => 'control-label' %>
<div class="controls">
<%= f.collection_select :type, Publication.order(:type), :id, :type, include_blank: true, :class => 'text_field' %>
</div>
</div>
Are you sure type is permited as an accessible param in your controller
def publication_params
params.require(:publication).permit(:type)
end
Are you sure the values for your options in the select are the right ones ?
Why is your collection_select containing :id
<%= f.collection_select :type, Publication.order(:type), :id, :type, include_blank: true, :class => 'text_field' %>
instead of :type
<%= f.collection_select :type, Publication.order(:type), :type, :type, include_blank: true, :class => 'text_field' %>
Regarding your second question, the answer will rely on a javascript / client side implementation.
Using jQuery you would implement something like this
# JS ($=jQuery)
# assuming your type select has id='type_select'
# assuming your fields inside your form have class 'field'
$('#type_select').change(function(event){
current_type = $(e.target).val();
$(e.target).parents('form').children('.field').each(function(el,i){
if($.inArray($(el).attr('id'), form_fields_for(current_type)){
$(el).show();
}else{
$(el).hide();
}
});
});
var form_fields_for= function(type){
{ book_chapter: [field1_id, field2_id, field3_id, field4_id],
book_whole: [field1_id, field2_id],
conference_article: [field1_id],
journal_article: [field1_id, field2_id, field3_id, field4_id, field5_id]
}[type];
};
Another solution would be to set specific classes for each fields for each of your types:
If we take the same assumptions as above, you would have rails to show a form like this:
# pseudocode (html form)
form
field1 class='book_chapter book_whole conference_article journal_article'
field2 class='book_chapter book_whole journal_article'
field3 class='book_chapter journal_article'
...
And then you would hide or show these specific classes
# JS ($=jQuery)
$('#type_select').change(function(event){
current_type = $(e.target).val();
$('.' + current_type).show();
$(e.target).parents('form').children('.field').each(function(el,i){
if(!$(el).hasClass(current_type)){
$(el).hide();
}
});
});

Getting rid of form and use just button to create new record

Rails 3.1. I have the following:
// _form.html.erb
<%= form_for ([#country, #state], :remote => true) do |td| %>
<div id= "state_errors" style="display:none"></div>
<%= td.text_field :position, :id => "next_state" %>
<div class="actions">
<%= td.submit %>
</div>
<% end %>
// global.js
function nextState() {
Array.max = function( array ) {
return Math.max.apply( Math, array );
};
var getLastState = $("input.sortable_state_item_position").map(function() {
return $(this).val();
}).get();
getLastState.push("0");
return Array.max(getLastState) + 1;
}
$("input#next_state").val(nextState());
// states_controller.rb
class StatesController < ApplicationController
before_filter :load
def load
#country = Country.find(params[:country_id])
#states = State.all
end
def create
#state = #country.states.build(params[:state])
#state.save
end
...
end
You will notice that I created a form tag for user to create a record when the submit button is clicked. But I am not sure if I could get rid of the entire form_for and just use a normal a or button to trigger the create because I kinda thing that the entire form is redundant as there is no need for the user to input anything. My javascript enters the value automatically.
Please advise. Many thanks.
In my State controller:
def create
#state = #country.states.build(params[:trip_day])
#state.position = State.where(:country_id => #country.id).maximum(:position).to_i + 1
#state.save
end
Replace the form with this:
<%= link_to "Add new state", country_states_path(#country), :remote => true, :method => :post %>
I removed the nextState() function, entire form.

Categories

Resources