Prior to Rails 3, I used this code to observe a field dynamically and pass the data in that field to a controller:
<%= observe_field :transaction_borrower_netid,
:url => { :controller => :live_validations, :action => :validate_borrower_netid },
:frequency => 0.5,
:update => :borrower_netid_message,
:with => "borrower_netid" %>
I'm trying to update that code to work with Jquery and Rails 3, but I can't get it to work. I updated my routes.rb to include
match "/live_validations/validate_borrower_netid" => "live_validations#validate_borrower_netid", :as => "validate_borrower"
and I'm trying to observe the field and make the necessary calls with:
jQuery(function($) {
// when the #transaction_borrower_netid field changes
$("#transaction_borrower_netid").change(function() {
// make a POST call and update the borrower_netid_message with borrower_netid
$.post(<%= validate_borrower_path %>, this.value, function(html) {
$("#borrower_netid_message").html(html);
});
});
})
but it's not working. My Javascript and Jquery skills are severely lacking, so any help anyone could provide would be much appreciated. Thanks!
You need to wrap your <%= validate_borrower_path %> in quotes:
$.post("<%= validate_borrower_path %>", this.value, function(html) {
I ended up using the following:
$('#transaction_borrower_netid').live('change', function() {
// when the #transaction_borrower_netid field changes
// make a POST call and replace the content
var netID = $('#transaction_borrower_netid').val();
$.post("/live_validations/validate_borrower_netid", { borrower_netid: $('#transaction_borrower_netid').val() }, function(html) {
$("#borrower_netid_message").html(html);
});
})
Related
Background
This is a crisp explanation of what I am trying to do:
I have a Rails form (am calling it a 'pre-search' form) which contains a dropdown
When the dropdown selection is changed, a search form is displayed to the user (the form allows the user to select some search criteria)
This form contains a "Run Search" button which is used to submit the form selections
When "Run Search" is clicked on the above form, a datatable is displayed right below the form
The Issue
And this is my issue:
When the search criteria in the above form is changed and "Run Search" is clicked again, I would like:
I. The datatable that was displayed earlier to be removed and
II. A new datatable to be displayed in the place where the old datatable was displayed.
But this does not happen. I see that additional datatables get added to the page instead of deleting the old one and replacing it everytime. So if I run search 4 times, I see 4 datatables in the page. I would like to see only 1 datatable how many ever times I run the search.
Code
This is my pre-search form with a dropdown:
<%= form_for :anything, remote: true, html: { id: 'pre_search_form' } do |f| %>
<div style="margin-left: 10px; margin-top: 10px">
<div class="col-lg-2">
<div class="form-group">
<label style="font-weight: 600;font-size:95%"><b>Category : </b> <%= select_tag(:search_category, options_for_select([['-Select-', ''], ['Option1', 'o1'], ['Option 2', 'o2'], ['Option 3', 'o3'], ['Option 4', 'o4']], :selected => 0)) %></label>
</div>
</div>
</div>
<!-- end of row 1 -->
</div>
<div id="dummy_div"> </div>
<div id="datatable_div"></div>
<% end %>
<script type='text/javascript'>
$(function() {
$(document).on("change", "#search_category", function(event){
$.ajax('show_search_form', {
type: 'GET',
dataType: 'script',
data: {
search_category: $("#search_category").val()
},
error: function(jqXHR, textStatus, errorThrown) {
return console.log("AJAX Error: " + textStatus);
}
});
});
});
</script>
This is the routes entry that gets called when the dropdown selection is changed in the above 'pre-search' form:
routes.rb
get "/show_search_form" => "search#show_search_form", :as => :show_search_form
This is the controller function that is executed due to the routes entry above:
search_controller.rb
class SearchController < ApplicationController
def show_search_form
render :partial => "search/show_search_form.js.erb"
end
This is the partial rendered by above controller function:
search/show_search_form.js.erb
<%= form_for :anything, remote: true, html: { id: 'search_form' } do |f| %>
<div class="row">
<b><%= label_tag "Entity" %><br/></b>
<%= select_tag(:search_entity, options_for_select([["Entity 1", 1], ["Entity 2", 2]]) %>
</div>
<%= button_tag 'Run Search', type: 'button', class: 'btn btn-primary btn-sm', id: "search_run_button" %>
<%end%>
<!-- Javascript code to handle events for dropdowns in the above form-->
<script type='text/javascript'>
/* Handle event when "Run Search" button is clicked */
$(document).on("click", "#search_run_button", function(event){
$.ajax('search_run', {
type: 'GET',
dataType: 'script',
data: {
search_entity: $("#search_entity").val()
},
error: function(jqXHR, textStatus, errorThrown) {
return console.log("AJAX Error: " + textStatus);
}
});
});
</script>
This is the routes entry for the button click in above form:
get "/search_run" => "search#run_search", :as => :search_run
This is the controller function called by the routes entry above:
def run_search
logger.info "SearchController run_search"
$search_entity = params[:search_entity]
data_table = SearchDatatable.new(view_context)
respond_to do |format|
format.html
format.json do
render json: {
"pageLength" => data_table.page_length,
"recordsTotal" => data_table.records_total,
"recordsFiltered" => data_table.records_filtered,
"data" => data_table.run_data
}
end
end
render :partial => "search/run_search.js.erb"
end
This is the partial called by the controller function above:
search/run_search.js.erb
$('#datatable_div').hide();
$('#datatable_div').hide().after('<%=escape_javascript(render(:partial => 'search/run_search')) %>');
As you can see, I am hiding datatable_div before rendering the datatable. But still, datatables get appended to the page instead of being overwritten.
How can I overwrite the datatable_div everytime so that irrespective of the number of searches done on the page, ONLY ONE datatable gets shown ALWAYS?
Please help!
This is the datatable rendering code just in case this is relevant:
search/run_search.html.erb
<div id="datatable_div">
<%= content_tag :table,
role: :search_datatable,
id: 'search_datatable',
style: 'height:500px; width: 100vw; overflow-y: auto;',
class: 'table table-striped table-bordered table-hover',
data: { url: search_datatable_path(format: :json)} do %>
<thead>
<tr>
<th>Column1</th>
<th>Column2</th>
</tr>
</thead>
<tbody>
</tbody>
<% end %>
</div>
<script>
$(document).ready(function(){
$("table[role='search_datatable']").each(function(){
var table = $(this).DataTable({
columnDefs: [
{ "orderable": true, "targets": 1},
],
aoColumns: [
{ mData: 'column1' },
{ mData: 'column2' }
],
autoWidth: true,
pageLength: 50,
processing: true,
serverSide: true,
sDom: 'ltipr',
ajax: $(this).data('url')
});
});
});
</script>
I tried these based on the comments from fellow stackoverflow users:
Approach 1 (based on #MikeHeft suggestion)
Approach 1. a)
$('#datatable_div').html('').html('<%=escape_javascript(render(:partial => 'search/dbr/run_search')) %>');
What happened with this approach?
This would not render the datatable even the very first time. It won't render any datatable - ever.
Approach 1. b)
$('#datatable_div').html('').after('<%=escape_javascript(render(:partial => 'search/dbr/run_search')) %>');
What happened after this approach?
This would render the datatable all right - but it still takes me back to my original issue - it won't replace the existing datatable the next time I run search. It just keeps adding more and more datatables to my search page.
I have an employee dropdown that lists all the employees. I want to be able to select an employee and get the address of the employee from the model so that I may display it. the following is the code of my collection_select.
<div class="form-group col-md-2 field">
<%= form.label :employee_id %>
<%= form.collection_select :employee_id, Employee.all, :id, :full_name,{:prompt=>"Select Employee"},{:id=>"emp_select",class:"form-control",:onchange=>"getEmployee();"} %>
</div>
Next is the code I am using to grab the value of the employee that was selected and it does work.
function getEmployee() {
var selectedVal=$('#emp_select option:selected').val();}
From here what do I do to get the address of the employee that was selected?
You will have to retrieve the employee's address via ajax call. Here are the steps:
Define an action in your rails app to return employee's address by json.
Make an ajax request to that action and get the info needed.
Render result into view.
For more information, take a look at this link:
https://guides.rubyonrails.org/working_with_javascript_in_rails.html
routes.rb
controller :ajax do
get 'ajax/get_employee_address/:employee_id', action: :get_employee_address, as: :get_employee_address
end
ajax_controller.rb
class AjaxController < ActionController::Base
def get_employee_address
employee = Employee.find(params[:employee_id])
render json: employee.address.to_json
rescue ActiveRecord::RecordNotFound
render json: 'Employee not found', status: 422
end
end
Your js code
function getEmployee() {
var selectedVal=$('#emp_select option:selected').val();
$.ajax({
url: '/ajax/get_employee_address/' + selectedVal,
success: function (address) {
// Render your address to view
},
error: function () {
// Handle error here or just return nothing
return null;
}
})
}
Note: This ajax endpoint will expose your employee address to outside so be sure to make authentication to prevent leaking info.
Add address to option data-attribute:
<%= form.select :employee_id,
options_for_select(Employee.all.map {
|e| [e. full_name, e.id, { 'data-address' => e.address }]
}),
{ prompt: "Select Employee" },
{ id: "emp_select", class: "form-control", onchange: "getEmployee();" } %>
On change get it with js:
function getEmployee() {
var selectedVal=$('#emp_select option:selected').data("address");}
And insert it to needed place
I have a page that does a search, using javascript, and I want to take the list of users that it comes up with, and send that as a submit to the next page. What I have, is:
.search_client_users
= form_tag admin_clients_path, method: "get" , class: "search_form" do
= label_tag 'search_term', 'Old domain name:'
= text_field_tag 'search_term', nil, autocomplete: "off", size: "50"
.main_form.client_emails
= simple_form_for(:domainNameSwap, url: { action: "update" }, html: { method: :put }) do |f|
.input-row
= f.hidden_field :users, value: #clients
.submit-row
.row
.col-xs-5
.submit
= f.submit "Update domains", id: "submit", :class => "btn btn-primary submit"
.client_list
- content_for :javascript do
= javascript_include_tag 'admin/search_client_users'
[some of the formatting may not be quite right due to cut and paste, sorry]
The admin/search_client_users creates an #clients, I'm pretty sure, at least, with:
class App.ClientUserList
constructor: ->
#incrementalSearchAttempts = 0
search: (searchTerm, completeCallback) =>
handleResponseWithOrderAwareness = (attemptNumber, response) =>
if attemptNumber >= #incrementalSearchAttempts
completeCallback(response)
#incrementalSearchAttempts++
onComplete = _.partial(handleResponseWithOrderAwareness, #incrementalSearchAttempts)
$.get('/admin/manage_clients/client_list', { search_term: searchTerm }).complete(onComplete)
class App.Views.SearchClientUsers extends Backbone.View
events:
"keyup input[name='search_term']": "search",
"click .profile_attribute": "showClientUserProfile"
initialize: =>
#clientUserList = new App.ClientUserList()
search: =>
searchTerm = $('.search_form input[name=search_term]').val()
#clientUserList.search(searchTerm, #render)
showClientUserProfile: (event) =>
window.location = $(event.currentTarget).closest('tr').data('client-path')
render: (response) =>
#$el.find('.client_list').html(response.responseText)
$ ->
new App.Views.SearchClientUsers(el: $('.search_client_users')).search()
so, I'm trying to take the list of clients, and send it to the update method in the controller. However, due to when javascript and ruby take place, it doesn't seem to be working... is there a way to do this? or do I have to figure out how to do this in Ajax?
ETA: An alternative idea is, I suppose to just turn the initial text_field into a form, so that the text field is used both for the javascript, and THEN submitted to the form, and then the update can re-do the search... My dataset is small enough that doing the search twice is not a huge problem I suppose...
But I'm not quite sure exactly how to merge the two forms...
I am working on rails 5 app. i am trying to load the data asynchronously form pgsql using jquery-select2 data is loading perfectly on search. but the problem is, i want to show the select2 tag when radio button is selected. i have two [radio buttons][1]. code for radio buttons is following
`
<%= radio_button(:new, :agent, :yes, { required: true, checked: true,
class: 'invite-rb' }) %>
<%= label_tag :new_agent_yes, 'New Agent' %>
<%= radio_button(:new, :agent, :no, { required: true, class: 'invite-rb' }) %>
<%= label_tag :new_agent_no, 'Existing Agent' %>`
I want to show the select2 box when user clicks on existing agent. but jquery-select2 is not applied to the select box.
here is my code for agent.js
$(document).on('turbolinks:load', function() {
$('.invite-rb').change(function() {
if(this.value == 'yes'){ //when i change this value to 'no' every thing works perfectly but not working with this condition
$('#agents').removeAttr('required')
$('#agent_first_name, #agent_last_name, #agent_email, #agency_code, #agent_code').attr('required', true)
$('#existing-agent-fields').addClass('hidden')
$('#new-agent-fields').removeClass('hidden')
$('#applications-div').addClass('hidden')
}
else{
$('#agent_first_name, #agent_last_name, #agent_email, #agent_agency_code, #agent_agent_code').removeAttr('required')
$('#agents').attr('required', true)
$('#existing-agent-fields').removeClass('hidden')
$('#new-agent-fields').addClass('hidden')
$('.chosen-select').select2()
$('#applications-div').addClass('hidden')
$('.chosen-select').select2({
minimumInputLength: 2,
placeholder: "Search by Agency code, agent code, name or email",
ajax: {
url: "/dashboard/agent_invitations/search_agents",
dataType: 'json',
type: 'GET',
data: function (term) {
return { q: term }
},
processResults: function (data) {
return { results: data.results }
}
}
});
}
});
i don't know whats wrong with this conditions. i don't want to change the values assigned to radio buttons because complete logic of this page depends upon them.
agent.js [1]: https://i.stack.imgur.com/AYrel.png
I have a form that allows the user to choose a country. Depending on which country is selected, I need to change the State/Province drop-down to include either a list of states or a list of provinces. I was going about this using the observe_field tag, but that was depreciated in rails 3...
So.., how should one go about this now? I am using select_tag to populate the drop-downs, and the arrays used in the options_for_select are all stored server-side and made accessible in the controller action, so I can't access them from javascript..
Using the Carmen gem: https://github.com/jim/carmen.
I did the following some times ago (AJAX).
HTML:
<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>
Controller:
def states
begin
render :json => Carmen::states(CGI::unescape(params[:country]))
rescue
render :json => {"content" => "None"}.to_json
end
end
Javascript with jQuery:
$('#profile_country').change(function() {
if ($(this).val() == '')
{
$('#profile_state').empty();
$('#profile_state').append( $('<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')
{
$('#profile_state').empty();
$('#profile_state').append( $('<option>No state provided for your country</option>'));
}
//handle the case where no state related to country selected
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>'));
});
}
}
});
}
});