Rails | Ajax Response, from Controller - ruby-on-rails

Got a partial view successfully interacting with my coffee script. Collection_Select change triggers script & resulting value is correct, Controller does hit def new successfully.
Only question remaining is how to access the results of the coffee script in the controller.
Partial View:
<% #modName = locals[:moduleName] %>
<% #id = locals[:id] %>
<%= form_with url: admin_command_path() do |f| %>
<%= collection_select(:refcode, :Code, Command.where(FLD: #modName), :Code, :Definition, options ={prompt: true}) %>
<br /><br />
<button class="btn_new">
<%= link_to "Execute", new_admin_command_path(mod: #modName, id: #id) %>
</button>
<% end %>
Coffee Script:
get_SubModule = ->
$('#refcode_Code').change (e) ->
com_value = $('#refcode_Code').val()
console.log 'COFFEEE IS LIFE', com_value
str = $('#refcode_Code :selected').text()
data: {sub_mod_str: com_value}
return
return
So now what.
ActiveAdmin.register Command do
def new
[need to access sub_mod_str here however possible]
end

I think when you Change value you need call Ajax and request controller
get_SubModule = ->
$('#refcode_Code').change (e) ->
com_value = $('#refcode_Code').val()
console.log 'COFFEEE IS LIFE', com_value
str = $('#refcode_Code :selected').text()
data: {sub_mod_str: com_value}
$.ajax(
type: 'POST'
url: your_url
data: data
dataType: 'json'
success: (data) =>
console.log(data)
error: (er) =>
console.log(er)
)
return
return
Controller
def new
byebug // check params
end

Related

how to process form_with using GET request as XHR

I'm working on a Rails 6 app, and want to update page view based on a dropdown value selected using XHR. Dropdown must use GET method coz I am calling index action.
I am using form_with which by default uses remote: true.
I am not using local: true.
I tried onchange: "Rails.fire(this.form, 'submit')" - this does send XHR request and receives a response but does not update view.
I tried onchange: "this.form.submit();" - this does a full page reload not utilizing XHR.
Code from app/views/users/index.html.erb
<%= form_with url: station_users_path(station_id: Current.user.home_station), method: :get do |form| %>
<%= form.select :user_status, options_for_select( { "Active users" => "unlocked", "Inactive users" => "locked"}, #user_status ), {}, { :onchange => "Rails.fire(this.form, 'submit')" } %>
<% end %>
Code from app/controllers/users_controller.rb
def index
#user_status = params[:user_status] || "unlocked"
#users = #station.users.send(#user_status) || []
#user_status == "unlocked" ? seperate_managers_from_users : #managers = []
end
In onchange just write one get_station_users() function. Inside that you can use ajax calling.
In forms
<%= form_with url: station_users_path(station_id: Current.user.home_station), id: “form_id”, method: :get do |form| %>
<%= form.select :user_status, options_for_select( { "Active users" => "unlocked", "Inactive users" => "locked"}, #user_status ), {}, { :onchange => "get_station_users()" } %>
<% end %>
Add Script
function get_station_users(){
$.ajax({
type: "GET",
url: "/station_users",
data: { $('#form_id').serialize(), },
dataType: 'script'
});
}
Your response will be as JS. So you can use index.js.erb

Filter select fields based on previous select fields values

I'm new at RoR and I'm having a trouble in my app. The problem consists on filter a select field named "Solution", based on the others select fields above it.
Now, what the app do is to retrieve all information from BD about Area, Region, Associated, Solution and populate the select fields with these data. But the user wants that, when an area, a region and an associated is selected by the user, only the solutions about that associated in that region on that area should be shown.
Edit:
I'm almost there! I've made many changes in my app. The select fields are populated by controller action new and the function "populate_selects", which is called by the parameter before_action :popula_selects, only: [:new, :edit]. A new function was created in order to be called by AJAX and upgrade the "Solution" field:
Atendments_Controller < ApplicationController
before_action :populate_selects, only: [:new, :edit]
def new
#atend = atendment.new
end
def update_solution #AJAX
#solutions = atendment.joins(:solution).where("atendment_area_id = ? and atendment_region_id = ? and atendment_assoc_id = ?", params[:atendment_area_id], params[:atendment_region_id], params[:atendment_assoc_id])
respond_to do |format|
format.js
end
end
private
def populate_selects
#atendment_area = atendmentArea.where(status: true, user_id: current_user.id)
#atendment_region = atendmentRegion.where(status: true, user_id: current_user.id)
#atendment_assoc = atendmentRegionAssoc.where(status: true, assoc_id: current_user.entidade_id).where(atendment_region_id: #atendment_region.map(&:atendment_region_id))
#solutions = atendment.joins(:solution).where("atendment_area_id = ? and atendment_region_id = ? and atendment_assoc_id = ?", params[:atendment_area_id], params[:atendment_region_id], params[:atendment_region_assoc_id])
end
end
Below, the _form.html.erb code from view:
<div class="atendment-form">
<%= form_for :atendment, url: {action: "new"}, html: {method: "get"} do |f| %>
<div class="col-xs-6">
<%= f.select :atendment_area_id, options_for_select(#atendment_area.collect { |c| [ c.atendment_area.name, c.id ] }, 1), {:prompt=>"Área"}, { :class => 'form-control', :required => true, id: 'atendment_atendment_area_id' } %>
</div>
<div class="col-xs-6">
<%= f.select :atendment_region_id, options_for_select(#atendment_region.collect { |c| [ c.atendment_region.name, c.id ] }, 1), {:prompt=>"Região"}, { :class => 'form-control', :required => true, id: 'atendment_atendment_region_id' } %>
</div>
</div>
</div>
<div class="field">
<%= f.select :atendment_assoc_id, options_for_select(#atendment_assoc.collect { |c| [ c.atendment_region.name, c.id ] }, 1), {:prompt=>"Associado"}, { :class => 'form-control', :required => true, id: 'atendment_atendment_assoc_id' } %>
</div>
<div class="field">
<%= f.select :solution_id, options_for_select(#solutions.collect { |solution| [solution.name, solution.id] }, 0), {:prompt=>"Solução"}, { :class => 'form-control', :required => true, id: 'atendment_solution_id' } %>
</div>
</div>
Route to the new function:
resources :atendments do
collection do
get :update_solution
end
end
AJAX function which calls the "update_solution" and reset solution field's value (app/assets/javascript/atendment.js.coffee):
show_solutions = ->
$.ajax 'update_solution',
type: 'GET'
dataType: 'script'
data: {
atendment_area_id: $("#atendment_atendment_area_id").val()
atendment_region_id: $("#atendment_atendment_region_id").val()
atendment_assoc_id: $("#atendment_atendment_assoc_id").val()
}
error: (jqXHR, textStatus, errorThrown) ->
console.log("AJAX Error: #{textStatus}")
success: (data, textStatus, jqXHR) ->
console.log("OK!")
$(document).ready ->
$('#atendment_atendment_assoc_id').on 'change', ->
show_solutions()
So, I've created a .coffee file to render the partial that will return a new value to the "solution" field "option" tag
(app/views/atendment/update_solution.coffee):
$("#atendment_solution_id").empty()
.append("<%= escape_javascript(render :partial => 'solution') %>")
And, the last but not least, the partial containing the html code for the "option" tag mentioned above (app/views/atendments/_solution.html.erb):
<option value="<%= solution.id %>" selected="selected"><%= solution.nome %></option>
For any reason, the AJAX function doesn't print nothing on console (nor error neither success), but it calls the update_solution.coffee file. The point is, it doesn't update the option value due an error (500 internal server error). I don't know what am I doing wrong. If anybody could help me, I appreciate it.
I would do this with JS, can think any other way.
A function called by onchange that change the display attribute from each field that you need to hide or show.
I solved this with the following code:
assets/js/atendments.js
I changed the code because the last one had many bugs.
function getAssociated(){
var aau_id = $("#atendment_area_user_id").val()
var aru_id = $("#atendment_region_user_id").val();
$.getJSON("/controllers/atendments_controller/getAssociated/"+aru_id,
function ( callback ) {
if (callback != "error"){
var assoc = document.getElementById("atendment_region_associated_id");
while (assoc.firstChild) {
assoc.removeChild(assoc.firstChild);
}
var i = Object.keys(callback).length -1;
$("#atendment_region_associated_id").append("<option value=''>Associated</option>");
while (i >= 0) {
$("#atendment_region_associated_id").append("<option value='"+callback[Object.keys(callback)[i]]+"'>"+Object.keys(callback)[i]+"</option>");
i--;
}
}
});
get_solution_type();
}
function get_solution_type() {
var ara_id = $("#atendment_region_associated_id").val();
$.getJSON("/controllers/atendments_controller/getSolution/"+ara_id,
function ( callback ) {
if (callback != "error"){
var sol = document.getElementById("atendment_solution_id");
while (sol.firstChild) {
sol.removeChild(sol.firstChild);
}
var i = Object.keys(callback).length-1;
while (i >= 0) {
$("#atendment_solution_id").append("<option value='"+callback[Object.keys(callback)[i]]+"'>"+Object.keys(callback)[i]+"</option>");
i--;
}
}
});
var aau_id = $("#atendment_area_user_id").val();
$.getJSON("/controllers/atendments_controller/getType/"+aau_id,
function ( callback ) {
if (callback != "erro"){
var type = document.getElementById("atendment_type_id");
while (type.firstChild) {
type.removeChild(type.firstChild);
}
var i = 0;
while (i < (Object.keys(callback).length)) {
$("#atendment_type_id").append("<option value='"+callback[Object.keys(callback)[i]]+"'>"+Object.keys(callback)[i]+"</option>");
i++;
}
}
});
}
The $.getJSON performs ajax request to the controller that responds with JSON and update the select fields option tags.
controllers/atendments_controller
I just retrieve the data from DB and return as JSON
def getAssociated
aru_id = params[:atendment_region_user_id]
aras = AtendmentRegionAssociated.where("SQL here")
if aras.present?
render :json => aras.to_json
else
render :json => "error".to_json
end
end
def getSolution
ara_id = params[:atendment_region_associated_id]
sol = Solution.where("SQL here")
if sol.present?
render :json => sol.to_json
else
render :json => "error".to_json
end
end
def getType
aau_id = params[:atendment_area_user_id]
type = AtendmentType.where("SQL here")
if type.present?
render :json => type.to_json
else
render :json => "error".to_json
end
end
Update the routes and put the javascript functions in select fields onchange property. Now everything is working fine :D

Ajax call on a <select> in a formtastic form

I need in my app to select from a list of provider a provider, and then, via ajax, I could see below a list of categories, that belongs to a specific provider. I have a form in activeadmin:
<%= semantic_form_for [:admin, #game], builder: ActiveAdmin::FormBuilder do |f| %>
<%= f.semantic_errors :state %>
<%= f.inputs do %>
<%= f.input :categorization_id, label: 'Provider', as: :select,
collection: Provider.all.map { |provider| ["#{provider.name}", provider.id] },
input_html: { class: (:provider_select), 'data-url': category_select_path(provider: 4) } %>
<%= f.input :categorization_id, label: 'Category',input_html: { class: ('category_dropdown') }, as: :select,
collection: Category.all.map { |category| ["#{category.name}", category.id]}%>
...
<% end %>
<%= f.actions %>
<% end %>
In activeadmin controller I have:
controller do
def ajax_call
#provider = Provider.find(params[:provider])
#categories = #provider.categories
respond_to do |format|
format.json { render json: #categories }
end
end
end
JS:
$(document).on('ready page:load', function () {
$('.select.input.optional').last().addClass('hidden_row');
$('#game_categorization_id').change(function () {
var id_value = this.value;
$('.hidden_row').removeClass('hidden_row');
$.ajax({
type: 'GET',
url: '/admin/games/category_select'
// data: id_value
})
});
});
And the routes: match '/admin/games/category_select' => 'admin/games#ajax_call', via: :get, as: 'category_select'
I don't have an idea, how can I pass providers id from collection into url. Currently, I have there category_select_path(provider: 4), but actually it has to be smth. like this - category_select_path(provider: provider.id) In the browser, in a Network tab of devtools I can see my category_select, but there is an error: Couldn't find Game with 'id'=category_select. I can't figure out from where does it come. Any suggestions? Thanks.
The problem was in routes: match '/admin/games/category_select' => 'admin/games#ajax_call', via: :get, as: 'category_select'. It is reserved by a show action of Activeadmin controller. So I changed my routes to: get '/admin/select_category' => 'admin/games#get_providers_categories', as: 'select_category', and added to ajax call data: {provider: provider}, so I could fire in params id of provider:
$.ajax({
type: 'GET',
url: '/admin/select_category',
data: {
provider: provider
},
success: (function (data) {
$('#select_category').children('option').remove();
$('#select_category').prepend('<option value=""></option>');
$.each(data.categories, function () {
$('#select_category').append('<option value="' + this.id + '">' + this.name + '</option>')
})
})
})

Using AJAX with two select boxes in Rails 4

I have a view containing two select boxes: company and employee. Both have a blank option and when a company is selected, it populates the employees based on the selected company. This works just fine. My issue is that when I submit a form that fails validation (as expected) and I select a company once more once the 'new' view renders again in extensions#create, my 'get' AJAX call has changed from /servers/1/extensions/get_company_employees (correct) to /servers/1/get_company_employees (incorrect) and is returning 404 Not found. Why is this happening and what should I do to remedy this? All relevant code is listed below
routes.config
resources :servers do
scope module: 'servers' do
resources :extensions, shallow: true
end
end
# Ajax call
get 'servers/:id/extensions/get_company_employees', to: 'servers/extensions#get_company_employees', as: 'get_company_employees'
app/controllers/servers/extensions_controller.rb
class Servers::ExtensionsController < ApplicationController
def get_company_employees
#server = Server.find(params[:id])
#extension = #server.extensions.build
#path = [#server, #extension]
#companies = Company.all
#employees = Employee.where("company_id = ?", params[:company_id])
respond_to do |format|
format.js
end
end
def new
#server = Server.find(params[:server_id])
#extension = #server.extensions.build
#path = [#server, #extension]
#companies = Company.all
#employees = Employee.none
end
def create
#server = Server.find(params[:server_id])
#extension = #server.extensions.build(extension_params)
#extension.password = "pass"
if #extension.save
flash[:success] = "Successfully created extension"
redirect_to #extension
else
#path = [#server, #extension]
#companies = Company.all
#employees = Employee.none
flash.now[:error] = "Failed to create extension"
render "new"
end
end
private
def extension_params
params.require(:extension).permit(:value, :password, :employee_id, :server_id, :phone_id)
end
end
app/views/servers/extensions/_form.html.erb
<%= form_for(#path) do |f| %>
<p>
<%= label_tag(:company) %>
<%= select_tag "company", options_from_collection_for_select(#companies, "id", "name"), include_blank: "Select a company" %>
</p>
<p>
<%= f.label(:employee) %>
<%= f.collection_select :employee_id, #employees, :id, :full_name, include_blank: "Select an employee" %>
</p>
<p>
<%= f.submit "Submit" %>
</p>
<% end %>
app/views/servers/extensions/get_company_employees.js.coffee
$("#extension_employee_id").empty()
.append("<option>Select an employee</option>")
.append("<%= j options_from_collection_for_select(#employees, :id, :full_name) %>")
app/assets/javascripts/servers/extensions.coffee
$ ->
$(document).on 'page:load', '#company', (evt) ->
$.ajax 'get_company_employees',
type: 'GET'
dataType: 'script'
data: {
company_id: $("#company option:selected").val()
}
$(document).on 'change', '#company', (evt) ->
$.ajax 'get_company_employees',
type: 'GET'
dataType: 'script'
data: {
company_id: $("#company option:selected").val()
}
Its because you have now specified complete URL in ajax call
It should be something like this in both cases.
$.ajax "/servers/"+ id +"/extensions/get_company_employees',
type: 'GET'
dataType: 'script'
data: {
company_id: $("#company option:selected").val()
}
// store and fetch id attribute from page in any of the dom element
Ideally you should write a function for your ajax call which can be called wherever required and code redundancy can be reduced.

Passing Ajax Parameters to Rails Controller

I am trying to pass some parameters from my view via an AJAX call to a custom method fetch_info in my photos controller. My controller does not seem to be receiving the parameters. When I click on an image to initiate the AJAX call, I see the following in my terminal:
Processing by PhotosController#fetch_info as JSON
Parameters: {"id"=>"", "secret"=>""}
Completed 500 Internal Server Error in 267ms
FlickRaw::FailedResponse ('flickr.photos.getInfo' - Photo not found):
app/controllers/photos_controller.rb:38:in `fetch_info'
It looks like the fetch_info method is being called, but the parameters are empty. How should I be passing in my parameters through AJAX?
Here is my view. I also have my javascript in the view for the purpose of just getting this to work.
index.html.erb
<div class="body_container">
<div id="photos_container">
<% #photos_array.each do |p| %>
<%= link_to '#' do %>
<div class='each_photo_container', id='<%="#{p[:id]}"%>' >
<%= image_tag p[:s_url] %>
</div>
<% end %>
<!-- Load Modal onClick -->
<script type="text/javascript">
jQuery(function() {
$('#<%=p[:id]%>').click(function (e) {
//ajax call to fetch photo info
var fetch_id = '<%=p[:id]%>';
var fetch_secret = '<%=p[:secret]%>';
$.ajax({
type: 'GET',
url: '/photos/fetch_info',
dataType: 'json',
data: { 'id' : fetch_id.val(), 'secret' : fetch_secret.val() }
});
return false;
});
});
</script>
<% end %>
<div class="basic_modal">
</div>
</div>
</div>
Here is my photos_controller.rb:
def fetch_info
puts params[:id]
puts params[:secret]
info = flickr.photos.getInfo(:photo_id => params[:id], :secret=> params[:secret])
end
You can use this code:
$('##{p[:id]}').click(function (e) {
//ajax call to fetch photo info
var fetch_id = '#{p[:id]}';
var fetch_secret = '#{p[:secret]}';
$.ajax({
type: 'GET',
url: '/photos/fetch_info',
dataType: 'json',
data: { 'id' : fetch_id, 'secret' : fetch_secret }
});
return false;
})

Resources