rails observe_field using ActionView Helpers - javascript

I have a select Menu with a few options
<p>
<%= f.label :reason %><br />
<%= f.select :reason, Confirmation.reasons.collect {|p| [ p[:name], p[:id] ] }, { :include_blank => true } %>
</p>
The last being id "5" and name = "Other"
If and only if they choose other I want a hidden text_area with a div id = "other" to be shown to allow the user to type...
How can I do this simply?
<%= link_to_function "Show me other" do |page|
page[:other].toggle
end %>
I can toggle it but I want to show it on the selection of the "Other" in the select box? Is this a job for observe_field?

Your own answer is fine, but for future reference, observe_field doesn't have to make an Ajax call. You can use :function to specify JavaScript code to run locally instead.
e.g.
<%=observe_field 'reason', :frequency => 1,
:function => "if ($('reason').value == '5') { $('otherform').show(); } else { $('otherform').hide(); }" %>

<%= f.select :reason, Confirmation.reasons.collect {|p| [ p[:name], p[:id] ] }, { :include_blank => true }, { :onchange => "if (this.value == '5') { $('otherform').show(); }" } %>
Got it!

Related

Unresponsive javascript when using collection_select?

I have just started learning rails, html and javascript. I am using a collection_select to allow a user to select other users in the database:
<%= f.collection_select :id, Customer.where(business_id: current_customer.business_id), :id, :full_name, :prompt => 'Select', :html => { :id => "colleageselect", :onChange => "renderColCal(this)"} %>
<div id = colleaguecal> </div>
I have just been trying to test whether onChange works, by using the javascript:
<script type = "text/javascript">
function renderColCal(select){
alert('this is a test' + select.valueOf() );
document.getElementById("colleaguecal").innerHTML = "foo"
}
</script>
But changing the collection_select value when running the page doesn't do anything? Am I missing something here?
check the generated html if it is what you are expecting. I don't see any issues with the js although it would be better if it was unobstrusive. The only thing that may have caused your issue is that you didn't just passed a hash to the html options. Try
f.collection_select :id,
Customer.where(business_id: current_customer.business_id),
:id,
:full_name,
{ prompt: 'Select' },
{ id: "colleageselect", onChange: "renderColCal(this)" }

Rails Simple Form Bootstrap - Javascript if statement to reveal input

I have a rails 4 app with simple form and bootstrap.
I want to ask a question in my form which asks whether users need survey responses. If the answer to that is true, then I want to ask a follow up question. My two survey questions are:
<%= f.input :survey, :as => :boolean, :label => false, inline_label: 'Do you need survey responses?' %>
<br><br>
<%= f.input :survey_link, label: 'Where is your survey?', :label_html => { :class => 'question-data' }, placeholder: 'Include a link to your survey', :input_html => {:style=> 'width: 650px; margin-top: 20px', class: 'response-project'} %>
Is JS if statement the best way to approach this task? I want to hide the second question until the user answers true to the first question.
If so, I'm having trouble understanding how to make this JS work.
I have tried:
if (:survey is :true) {
:survey_link;
}
I can't find any resources to help explain how to do this. Help would be very much appreciated. Thank you.
Obviously the code below depends on what the name of your survey and survey_link inputs look like in actual HTML. So if in this example it is for #user:
<% simple_form_for #user do |f| %>
<%= f.input :survey, :as => :boolean, :label => false, inline_label: 'Do you need survey responses?' %>
<%= f.input :survey_link, label: 'Where is your survey?', :label_html => { :class => 'question-data' }, placeholder: 'Include a link to your survey', :input_html => {:style=> 'width: 650px; margin-top: 20px', class: 'response-project'} %>
<% end %>
Then the JQuery should look like (note the user part - you may have to change this):
<script>
$(function() {
// Hide the survey_link input
$('input[name="user[survey_link]"]').hide();
$('input[name="user[survey_link]"]').closest("label").hide();
// When the survey checkbox changes
$('input[name="user[survey]"]').change(function() {
$('input[name="user[survey_link]"]').closest("label").toggle(this.checked);
$('input[name="user[survey_link]"]').toggle(this.checked);
});
});
</script>

Complex Cascading Dropdown in Rails won't work in Edit Form

I recently tried to implement a cascading dropdown into my application with this tutorial on petermac.com: http://www.petermac.com/rails-3-jquery-and-multi-select-dependencies/
The tutorial basically talks about doing a cascading dropdown, where every dropdown box is an a separate partial and gets loaded with an jQuery onChange event when the parent select is changed.
Now I got this to work without a problem. But actually my select boxes have quite complicate relationships between them.
So, the form I belongs to a Model called AuditFunction and as the name says is for auditing. Every audit has a source and a target, which can be compared via several commands. The source as well as the target are selected via 3 select boxes. The first box selects the type of database the field is in. The second box selects the table and then the third box selects the field. As the field box can contain thousands of options I tried to implement the cascading dropdown to make it easier for the user to select the field.
To give you an overview, this is what my actions look like:
# new.html.erb
<%= simple_form_for #audit_function do |f| %>
<%= f.input :database_1, :as => :select, :collection => #databases, :include_blank => true %>
<%= render :partial => 'databases_1' %>
<%= render :partial => 'fields_1' %>
<%= f.input :database_2, :as => :select, :collection => #databases, :include_blank => true %>
<%= render :partial => 'databases_2' %>
<%= render :partial => 'fields_2' %>
<% end %>
The javascript for this looks like this:
# jQuery
<script type='text/javascript' charset='utf-8'>
jQuery(function($) {
// when the #country field changes
$("#audit_function_database_1").change(function() {
var database_1 = $('select#audit_function_database_1 :selected').val();
if(database_1 == "") database_1="0";
jQuery.get('/audit_functions/update_database_1_id_select/' + database_1, function(data){
$("#database_1_id").html(data);
})
return false;
});
})
</script>
<script type='text/javascript' charset='utf-8'>
jQuery(function($) {
// when the #country field changes
$("#audit_function_database_2").change(function() {
var database_2 = $('select#audit_function_database_2 :selected').val();
if(database_2 == "") database_2="0";
jQuery.get('/audit_functions/update_database_2_id_select/' + database_2, function(data){
$("#database_2_id").html(data);
})
return false;
});
})
Now I'm only going to show you the partials for database_1_id and field_1_id, but they look the same as database and field 2.
# _databases_1.html.erb
<script type="text/javascript">
jQuery(function($) {
$("#audit_function_database_1_id").change(function() {
var database_1_id = $('select#audit_function_database_1_id :selected').val();
if(database_1_id == "") database_1_id="0";
jQuery.get("/audit_functions/update_field_1_id_select/" + ("<%= params[:id] %>_" + database_1_id), function(data){
$("#field_1_id").html(data);
})
return false;
});
})
</script>
<%= simple_form_for "audit_function" do |f| %>
<% if params[:id] %>
<% if params[:id] == "imp" %>
<%= f.input :database_1_id, collection: AdOriTbl.all.order(ori_filename: :asc).collect{ |a| [a.ori_filename,a.id]} %>
<% elsif params[:id] == "ori" %>
<%= f.input :database_1_id, collection: AdOriTbl.all.order(otb_filename: :asc).collect{ |a| [a.otb_filename,a.id]} %>
<% elsif params[:id] == "mod" %>
<%= f.input :database_1_id, collection: AdQryMod.all.order(qry_mod_text: :asc).collect{ |a| [a.qry_mod_text,a.id]} %>
<% end %>
<% end %>
<% end %>
And now the file containing the target field.
# _fields_1.html.erb
<%= simple_form_for "audit_function" do |f| %>
<% if params[:id] %>
<% if params[:id].gsub(/_{1}\d{1,}\z/, "") == " mod " %>
<%= f.input :field_1_id, collection: AdQryFld.where(ad_qry_mod_id: params[:id].gsub(/\A\w{1,}_{1}/, "").to_i).order(order_id: :asc).collect{ |f| [f.qry_field_text,f.id]} %>
<% else %>
<%= f.input :field_1_id, collection: AdOriFld.where(ad_ori_tbl_id: params[:id].gsub(/\A\w{1,}_{1}/, "").to_i).order(id: :asc).collect{ |f| [f.otb_colhdg,f.id]} %>
<% end %>
<% end %>
<% end %>
The controller then contains all the actions triggered in the javascripts:
# audit_function_conroller.rb
def new
authorize! :new, :audit_functions
#audit_function = AuditFunction.new
#functions = [[I18n.t("text sum"),"sum"],[I18n.t("text quantity"),"quantity"],[I18n.t("text largest_value"),"largest_value"],[I18n.t("text smallest_value"),"smallest_value"]]
#databases = [[I18n.t("text original_database"),"imp"],[I18n.t("text archive_database"),"ori"],[I18n.t("text query_database"),"mod"]]
end
def update_database_1_id_select
if params[:id] == "mod"
type = "mod"
elsif params[:id] == "ori"
type = "ori"
elsif params[:id] == "imp"
type = "imp"
end
render partial: "databases_1", id: type
end
def update_field_1_id_select
type = params[:id]
render partial: "fields_1", id: type
end
Now, as messy as all of this looks, the good thing is that it gets the job done. And to clarify my MVC, these are the relations:
AdOriTbl has_many AdOriFlds
AdOriFld belongs_to AdOriTbl
AdQryMod has_many AdQryFlds
AdQryFld belongs_to AdQryMod
I hope the names don't bother you too much when reading this.
Now lets get back to the problem:
As I said this code works for creating a new object and everything is selected fine. But when I try to edit an object only the field with the database type (database_1 and database_2) are filled. The select boxes for the ID's of the databases are not rendered, while the boxes for the fields are. But all four ID fields are empty.
Now I already tried to fill the boxes by hand with a jQuery that basically looks similar to the ones I already have, but instead of getting triggered onChange, I trigger it when my audit_function has a database_id and render the select box and fill it with the value according value of database_id. This works as well.
The problem is that I can't do this with the field_id, because in the partial of database_1_id where the jQuery for the fields get triggered, I don't have the #audit_function object at hand and also it seems to interfere with the other javascripts.
Besides that I'd also like to think that there is a better way to do this, then my way. But I already tried other tutorials and ways and they either don't work when you don't have your straight-forward Country-State-City relationships or they don't work when editing.
So, any help would be really appreciated. Thanks!
I took the following tutorial as template to rewrite my cascading dropdown:
http://homeonrails.blogspot.de/2012/01/rails-31-linked-dropdown-cascading.html
So, now I throw all the different models into one array and filter it by appending names to the class, to differentiate not only by ID, but also by name. Also the jQuery Plugin chainedTo makes the code much more readable.
So, the controller looks now like this:
#types_for_dropdown = [[I18n.t("text archive_database"),"ori"],[I18n.t("text query_database"),"mod"]]
#tables_for_dropdown = []
#ad_qry_mods = AdQryMod.all
#ad_qry_mods.each do |i|
#tables_for_dropdown = #tables_for_dropdown << [i.qry_mod_text,"mod#{i.id}",{:class => "mod"}]
end
#ad_ori_tbls = AdOriTbl.all
#ad_ori_tbls.each do |i|
#tables_for_dropdown = #tables_for_dropdown << [i.otb_filename,"ori#{i.id}",{:class => "ori"}]
end
#fields_for_dropdown = []
#ad_qry_flds = AdQryFld.all
#ad_qry_flds.each do |i|
#fields_for_dropdown = #fields_for_dropdown << [i.qry_fieldname,i.id,{:class => "mod#{i.ad_qry_mod_id}"}]
end
#ad_ori_flds = AdOriFld.all
#ad_ori_flds.each do |i|
#fields_for_dropdown = #fields_for_dropdown << [i.otb_fieldname,i.id,{:class => "ori#{i.ad_ori_tbl_id}"}]
end
And the form looks like this:
<%= content_for :head do %>
<script>
$(document).ready(function(){
$('select#audit_function_database_1_id').chainedTo('select#audit_function_database_1');
$('select#audit_function_field_1_id').chainedTo('select#audit_function_database_1_id');
$('select#audit_function_database_2_id').chainedTo('select#audit_function_database_2');
$('select#audit_function_field_2_id').chainedTo('select#audit_function_database_2_id');
});
</script>
<% end %>
<div class="grid-6-12">
<%= f.input :database_1, label: I18n.t("field_label audit_function database_1"), hint: I18n.t("field_hint audit_function database_1"), as: :select, collection: #types_for_dropdown, include_blank: true %>
</div>
<div class="grid-6-12">
<%= f.input :database_2, label: I18n.t("field_label audit_function database_2"), hint: I18n.t("field_hint audit_function database_2"), as: :select, collection: #types_for_dropdown, include_blank: true %>
</div>
<div class="grid-6-12">
<%= f.input :database_1_id, label: I18n.t("field_label audit_function database_1_id"), hint: I18n.t("field_hint audit_function database_1_id"), as: :select, collection: #tables_for_dropdown, include_blank: true %>
</div>
<div class="grid-6-12">
<%= f.input :database_2_id, label: I18n.t("field_label audit_function database_2_id"), hint: I18n.t("field_hint audit_function database_2_id"), as: :select, collection: #tables_for_dropdown, include_blank: true %>
</div>
<div class="grid-6-12">
<%= f.input :field_1_id, label: I18n.t("field_label audit_function field_1_id"), hint: I18n.t("field_hint audit_function field_1_id"), as: :select, collection: #fields_for_dropdown, include_blank: true %>
</div>
<div class="grid-6-12">
<%= f.input :field_2_id, label: I18n.t("field_label audit_function field_2_id"), hint: I18n.t("field_hint audit_function field_2_id"), as: :select, collection: #fields_for_dropdown, include_blank: true %>
</div>
This is really a nice solution and I can recommend it to everyone!

Changing Multiple select fields in ruby on rails

I have a two f.select fields in my form with the same object id. I am changing these fields by selecting the parent field using javascript and CSS.
<%= f.label :Service_Phase, 'Service Phase' %>
<%= f.select :Service_Phase, [], { :prompt => 'None' }, class: 'select_phase', disabled: 'disabled' %>
<%= f.select :Service_Phase, (1..52), { :prompt => 'Select Week' }, class: 'select_week' %>
<%= f.select :Service_Phase, (1..12), { :prompt => 'Select Month' }, class: 'select_month' %>
I want to display the select box disabled with the text 'NONE' by default and will change the select_field by the parent select field value. Is it any other neat way to do this in rails? Because when i try to the check the value after selected the value of week in console, its display the empty string. I don't know where am doing wrong and how can I correct this? Thanks in advance.
I think you might be better off just doing that with javascript/jquery. I don't believe rails has a built in way to enable a secondary select field based off the first.

Auto populate a text field based on another text field

I am trying to auto-populate a text field based on the value of another input field. Currently trying to do this using observe_field helper like this:
<%= observe_field(
:account_name,
:function => "alert('Name changed!')",
:on => 'keyup'
) %>
<% form_for(#account, :html => { :id => 'theform' }) do |f| %>
<label for="accountname"> Account name </label>
<%= form.text_field :name, :tabindex => '1' %>
<label for="subdomain"> Subdomain </label>
<%= form.text_field :subdomain, :tabindex => '2' %>
<% end %>
When the user enters text in the account_name text_field, I want to copy that convert into a subdomain (downcase and join by '-') and populate to subdomain text_field.
But, in the process getting this error:
element is null
var method = element.tagName.toLowerCase(); protot...9227640 (line 3588)
Where exactly am I going wrong here? Or is there a better way to do this?
Put your "observe_field" inside the form tag and try again.
EDITED
your observe_field needs to be after the thing it's observing.
Hope that helps :)
For ex:-
<% form_for(#account, :html => { :id => 'theform' }) do |f| %>
<label for="accountname"> Account name </label>
<%= form.text_field :name, :tabindex => '1' %>
<%= observe_field(
:account_name,
:function => "alert('Name changed!')",
:on => 'keyup'
) %>
<label for="subdomain"> Subdomain </label>
<%= form.text_field :subdomain, :tabindex => '2' %>
<% end %>

Categories