one f.select is affecting another within the same form? (unwanted) - javascript

I have a problem where, when adding a new html element such as:
<%= f.date_select :date, { id: "date-select"} %>
it affects my already existing collection select:
<%= f.collection_select :id,
Customer.where(business_id: current_customer.business_id),
:id,
:full_name,
{ prompt: 'Select' },
{ id: "colleague-select", onChange: "renderColCal(this)" } %>
Usually, the customer can select another customer from the list, triggering an ajax call to render the selected customer's calendar using the selected customer's id. This works fine by itself.
However, when I put in this new date_select option further up in the form, and then try to use the collection_select, the ajax call can't be finished because it is trying to find a customer with an id equal to the year of the date that's been selected in the other select box!!
Here is an example. I have selected a date with the year "2012" in my date_select. Then I select a customer in the collection_select and receive this in the console:
Started GET "/calendars/calendar_change?colleagueID=2012" for 127.0.0.1 at 2016-02-01 11:38:01 +0000
Processing by CalendarsController#calendar_change as */*
Parameters: {"colleagueID"=>"2012"}
Customer Load (0.0ms) SELECT "customers".* FROM "customers" WHERE "customers"."id" = ? ORDER BY last_name ASC LIMIT 1 [["id", 2012]]
Completed 404 Not Found in 5ms
ActiveRecord::RecordNotFound (Couldn't find Customer with 'id'=2012):
app/controllers/calendars_controller.rb:19:in `calendar_change'
this is my javascript being called:
function renderColCal(select){
var colleagueID = select.value ;
$.ajax({
url: '/calendars/calendar_change',
data:{
colleagueID: $('select').val()
}
}
)
}
Why is this happening? How do I fix this? Thanks!

The problem is your javascript. The data you are submitting is
data:{
colleagueID: $('select').val()
}
which submit the value of the first select on the page. If you want to go that route, you'd have to make the selector you've passed to $() more selective (for example, using the id of the select box).
You are actually retrieving the value from the select box earlier in your event handler, but you're not using it for some reason. This is probably less error prone than using jquery to find the select element when it is already being passed to you.

Related

How to update single column using modal on one page based on ajax request

I have page who contains 3 boxes and all of these boxes's data need to update in one db table so I used to update all of them one by one using partial and custom ajax.
View Code:
.col-lg-3.col-md-3.col-sm-6.col-xs-6
.box-bar
h5.prodman Short Description
br
btn.btn-primary.btn-lg
= link_to 'Edit', edit_product_path(#product, field: 'sd'), remote: true
.col-lg-3.col-md-3.col-sm-6.col-xs-6
.box-bar
h5.prodman Long Description
br
btn.btn-primary.btn-lg
= link_to 'Edit', edit_product_path(#product, field: 'ld'), remote: true
.col-lg-3.col-md-3.col-sm-6.col-xs-6
.box-bar
h5.prodman T&Cs (General, Privacy, Fair Usage etc)
br
btn.btn-primary.btn-lg
= link_to 'Edit', edit_product_path(#product, field: 'tc'), remote: true
Upon clicking link_to the modal loads all those content:
edit.js.erb code:
<% field_name, field_title = get_field_name_title(params[:field]) %>
$('#dialog h4').html("<i class=' glyphicon glyphicon-pencil'></i> Update <%= field_title %>");
$('.modal-body').html('<%= j render('terms_field_form',{field_name: field_name}) %>');
$('#dialog').modal("show");
$('#dialog').on('shown.bs.modal', function () {
CKEDITOR.replace('<%= "#{field_name}" %>');
});
$(document).on('click', '.update_terms', function () {
$.ajax({
type: 'PATCH',
dataType: 'script',
url: '<%= product_path(#product) %>',
data: {
"authenticity_token": $('input[name=authenticity_token]').val(),
"product": {"<%= field_name %>": $('.terms_content').val()}
}
});
});
Partial Code:
= text_area_tag "#{field_name}".to_sym, #product.send(field_name), class: 'form-control terms_content', id: field_name
= button_tag 'Submit', class: 'btn btn-primary mg-t-20 mg-b-20 mg-r-10 update_terms'
Dynamic fields (column and titles ) code:
def get_field_name_title(field)
return 'short_description', 'Short Description' if field == 'sd'
return 'long_description', 'Lease Terms' if field == 'ld'
return 'terms_and_conditions', 'T&Cs (General, Privacy, Fair Usage etc)' if field == 'tc'
end
Problem
The boxes contents always remain same. Means, I am updating 'Long Description' and I will update it in db but if I try to update any other box it show the name of that box again ( the previous one I updated ).
I got an impression that on each click and updation the modal stay same and on next click its adding with existing once. And it iterates it to next click. So, click1, next time I clicked2, so click1,click2. then next time i clicked3, so click1,click2,click3. this is the issue.
So, no new fresh event to new click.
Is there any proper way to do it if my process lags any feature?
You are having issues because you haven't fully committed to the single page paradigm. I'm not sure of the interaction with CKEDITOR, but the 3 warning signs I see ...
1) Your update doesn't work, but create does
2) Your code is randomly populating all of the fields with the same data
3) Your code has no unique identifier for the fields in the css/html
You need to uniquely identify the fields which will be altered.
Note: all of this assumes that you are intending to treat each field separately as it's own form - I'm not sure you make a conscious decision about which strategy to use - so I'm just following the lead of the questions you seem to be asking - as I said in the rails/ruby chat - the simplest way is to make it all one form, have a single update button for it and be done
Your div or id for the html code needs to reflect this fact, by being wrapped around those modal fields.
Which will allow you to use to jquery .bind & attach a trigger on just that field to run the update against server.
... example of us setting up a html class/div to anchor the jquery too ...
Old:
.col-lg-3.col-md-3.col-sm-6.col-xs-6
.box-bar
h5.prodman Short Description
br
btn.btn-primary.btn-lg
= link_to 'Edit', edit_product_path(#product, field: 'sd'), remote: true
New with class - (not tested but general idea):
.sd-class # -- note this can be any name, as long as sd/ld/tc aren't the same
.col-lg-3.col-md-3.col-sm-6.col-xs-6
.box-bar
h5.prodman Short Description
br
btn.btn-primary.btn-lg
= link_to 'Edit', edit_product_path(#product, field: 'sd'), remote: true
Next your simply setup an jquery binding based on that anchor - answered thousands of times - Modal updating with jquery.
I'm guessing here - but CKEDITOR should be able to take that modal field that is properly pointed too inside the anchoring div I pointed out to you ... see this answer for how to test and locate an element inside another to feed it the right field.
Note: the other part is that CKEDITOR MIGHT need to be set to nil/initialized each time you call it, to ensure blank or set to the field using the unique class div we setup as an anchor
See this answer for help selecting the right field with jquery
I feel like most of your issue is the code you wrote doesn't explicitly tell CKEDITOR where to find the information it's targeting & it's not reseting after each run. So you might have to initialize CKEDITOR each time - see their forums for help on that one.

Delete or hide some values in drop down list which is populating by stored procedure using JavaScript?

I'm working on Classic ASP and JavaScript.
I have two dropdown lists: Dropdownlist1 and Dropdownlist2. In first dropdown list it shows list of companies, in second dropdown list it shows departments.
When the user select the company A from 1st dropdown list so, it should show all of departments.
When the user selects the company B from 1st dropdown list, it should hide couple of departments in the 2nd dropdown list.
The dropdowns are populated from stored procedures.
How can I do this?
There's two ways to go with:
You can either use AJAX to make a Request to get the options for your second dropdown by passing the selection of the first one (that's what most people would do). That would look something like this in your JS (not tested!)
(Edit: forgot to mention that the example below uses jQuery)
$('select#company').on('change', function () {
$.ajax('/some-asp-file.asp', {
type: 'POST',
data: {
'Company': $('select#company').val()
},
success: $.proxy(function(data){
$('select#department').html(data);
}, this)
});
});
and something like this in /some-asp-file.asp (also not tested!)
<%
dim Company
dim Department, Departments
Company = trim(request.form("Company"))
if Company <> "" then
Departments = ' // -> Result Array from your SP here where you pass in "Company"
for each Department in Departments
%>
<option value="<%=Department%>"><%=Department%></option>
<%
next
else
%>
<option value="-1">-</option>
<%
end if
%>
OR (the decision also depends on the amount of data you have) you could initially get ALL the data and store it in a JS object and replace it client-sided. This is probably more frustrating to code with all the double quote escaping in ASP etc, but I could write you a quick example if you insist.

How to make a change event only run one time the event is called for a class

I'm designing a multi dynamic select menus, i.e., I have a menu for brands, after the user select the brand, using JavaScript and AJAX, I will search for the models available from that brand and add them to the second select menu. This process repeats again but this time showing the features of the model selected.
To do this, and because I have many different areas that need the same system, I use a class with the same name in every brand select menu and another one to every model select menu.
<div class='brand_select' id='14'>
<%= f.collection_select :brand, Product.find_all_by_area(14, :group => 'brand'), :brand, :brand, :prompt => 'Choose brand' %>
</div>
<div class='model_select'>
<%= f.collection_select :model, Product.find_all_by_area(14), :model, :model, :prompt => 'Choose model' %>
</div>
<div class='brand_select' id='15'>
<%= f.collection_select :brand, Product.find_all_by_area(15, :group => 'brand'), :brand, :brand, :prompt => 'Choose brand' %>
</div>
<div class='model_select'>
<%= f.collection_select :model, Product.find_all_by_area(15), :model, :model, :prompt => 'Choose model' %>
</div>
And the JavaScript:
$('.brand_select').change(function(event) {
// option selected
var brand=$(event.target).find('option:selected').val();
// if none is selected
if (brand == ''){
$(event.target).parent().parent().find('.modelo_select').hide();
$(event.target).parent().parent().find('.caracteristica').hide();
}
else {
$(event.target).parent().parent().find('.modelo_select').show();
// find id to search on the database
var id=$(event.target).parent().attr('id');
// find the target (id of the object)
var target=$(event.target).attr('id');
$.ajax({
type: "POST",
url: "http://"+location.host+"/model/"+brand+"/"+id+"/"+target,
brand: brand,
id: id,
target: target
});
}
});
$('.model_select').change(function(event) {
// find model selected to search on the database
var model=$(event.target).find('option:selected').val();
// find brand selected to search on the database
var brand=$(event.target).parent().parent().find('.marca_select').find('option:selected').val();
// find id to search on the database
var id=$(event.target).parent().parent().find('.marca_select').attr('id');
// find the target (id of the object)
var target=$(event.target).attr('id');
$.ajax({
type: "POST",
url: "http://"+location.host+"/feature/"+brand+"/"+model+"/"+id+"/"+target,
brand: brand,
model: model,
id: id,
target: target
});
});
This code works but it repeats the event change the same number of times as the classes with that name.
What I want to do is for the function to run only one time every time a change event is called for the class.
I don't know if this is possible with class structure that I have or if I have to associate an id or a class with different names for each area to the function.
I don't see why the event should fire twice because all you're doing with $(selector).change is saying that every time a change event fires on something with that selector you want to handle it. I even ran a quick test to be sure and it doesn't fire more than once.
Can you explain a bit better what the symptom actually is? As in, what actually happens twice? Does everything in your event handler happens twice?
I was thinking that your selectors for the actions you perform on the parents might be a bit too lax ($(event.target).parent().parent()) so if you only want to do something on the container where your event was fired that wouldn't be the best way (but then again I don't know what your end purpose is here).
That for your help, I found out that the problem has nothing to do with Javascript but is instead on the Ruby on Rails.
I was adding on application.html.erb other js files and if you have the //= require_tree on the application.js it adds every js file in the tree, so adding js files on application.html.erb will make them repeat and cause strange behaviors like this one.

Ruby on Rails - call Controller Method and pass Parameters to it

I have following situation:
I have a risk model and on my view it shows me a table with all risks. The table also includes a check_box_tag, as each risk should be able to be checked. In the tablehead there is a button and if this button is clicked, a method of the risk controller should be called, and it should have all checked risk IDs as parameter.
Actually, I don't know which would be the best way to solve this.
I have following code so far:
View:
<table>
<thead>
<tr>
<th>Risk Name</th>
<th>
<button id="mergerisks">Merge Risks</button>
</th>
</tr>
</thead>
<tbody>
<% Risks.all.each do |risk| %>
<tr>
<td><%= risk.name %></td>
<td><%= check_box_tag 'mergerisks', risk.id %>
</td>
</tr>
<% end %>
</tbody>
</table>
Javascript:
$( "#mergerisks" ).on( "click", function() {
var selectedriskmerge = new Array();
$("input:checked").each(
function() {
selectedriskmerge.push($(this).val());
});
});
Edit
Added the following ajax call to javascript
$.ajax({
url: '/riskmerge',
data:selectedriskmerge,
success:function() {
window.alert("Success!");
}
});
For now the Button only triggers the Javascript, and there are the ID's of all checked Risks are stored in an array.
But now I don't know what would be the best way to call a controller method in the risk controller and pass the IDs of all checked Risks to the method.
Thanks for any help.
NOTE: This is slightly different from what you wanted, but might provide a better user experience since they won't have to click an additional button at the end to update the records so heed with caution. No matter what though you will get a decent example of how to use ajax for your own needs.
First you need to create an action in the controller that updates the record you want which you already have. The twist is that instead of rendering html you will want to render json at the end. Something like this will do.
if risk.update_attribute(check: true)
render :json => { status: "Everything worked!"}
else
render :json => { status: "Something went wrong!"}
end
Next you will want to set up the javascript so that when a check box is clicked, an ajax post is sent to the action that updates the record. You have this partially done with your javascript. Inside your click event, you can have something like
$.post("/risk_update",
// This line below is the parameters sent to the action.
//So your action will recognize params[:risk_id]
{ risk_id: $(".clicked_check_box").attr("value") },
"json")
.done(function (responseText) {
if (responseText.status === "Everything worked!") {
// Do something on success of info being saved
} else if (responseText.status === "Something went wrong!") {
// Do something on failure of info being saved
}
});
Finally, there is a problem with the check box. Do you want the user to uncheck the box and call a record again. This of course goes beyond the discussion of the question but they are some things you have to keep in mind.
Of course in your case you will want to click a button that grabs all the ids and sends them to the action to update the records. One way would be to have javascript inject the id into an array when a check box is marked, then when the user clicks on the submit button the array is sent as params to the action that then loops through the arrays and updates the risks.
I'm sure there are better ways though, that's just the first thing that came to mind.
Your best bet would be to place all of the check boxes inside of a form.
<%= form_tag controller_method_name_your_controller_path, :method => 'get', do %>
...
<%= submit_tag 'submit' %>
<% end %>
Declare the path in the routes.rb file under your_controller
get :controller_method_name
You can group you check boxes together by using check_box:
<%= check_box 'mergerisks', risk.id %>
Then using params[:mergerisks] in the controller will return a hash with risk.id as the keys and a 1 or 0 depending on if the check box is checked.
Some documentation on routes and forms:
http://guides.rubyonrails.org/routing.html
http://guides.rubyonrails.org/form_helpers.html

ruby variable in javascript in rails function

I am trying to change the colour of a row according to a rails database value. Also within the row is a form which is a drop down menu. On changing the selected value in the drop down form I update the changed value to the DB by a form submit and then call a javascript function to change the row colour using the new value through AJAX.
html.erb:
<%= f.select(:status, ["to call","didn't connect","confirmed","rejected"], {:selected => lead.status}, :onchange => %Q[$('#lead_form_#{lead.id}').submit();document.getElementById('lead_row_#{lead.id}').bgcolor=Application.getRowColour("#{lead.status}");]) %>
In the above code what is happening is that the #{lead.status} which is being passed to getRowColour is always the same i.e. the initial value of status when I first load the page. So how many ever times I change the status via the dropdown, the getRowColour("") does not change.
source of the page:
$('#lead_form_133').submit();document.getElementById('lead_row_133').bgcolor=Application.getRowColour("confirmed");
As can be seen the getRowColour() is taking a constant value and not re-evaluating it on every call. How can I send my lastest status param to this function?
Assuming the id of the status select-box is status consider using the following construction:
<%= f.select(:status, ["to call","didn't connect","confirmed","rejected"],
{:selected => lead.status} %>
Then add the onchange handler logic:
<script type="text/javascript">
$("#status").change(function() {
$('#lead_form_#{lead.id}').submit();
$('#lead_row_#{lead.id}')
.css('background-color', Application.getRowColour($("#status").val())
});
</script>

Categories

Resources