how to make collection_select value as link_to variable - javascript

I have the ff:
app/views/reports/index.html.erb
<h1>Reports</h1>
<br>
<legend>Categories</legend>
<div class="row">
<div class="span5">
<ol>
<li><%= link_to 'COMMENDATION', commendations_path(format: 'pdf'), { id: 'commendations_click' } %></li>
<%= collection_select(nil,
:employee_id,
#employees,
:id,
:last_name,
{:prompt => "Select an Employee"},
{:id => 'employees_select'}) %>
<br>
<%= collection_select(nil,
:employee_movement_id,
#employeemovements,
:id,
:position,
{:prompt => "-"},
{:id => 'employee_movements_select'}) %>
<li><%= link_to 'REPORT2', '#' %></li>
<li><%= link_to 'REPORT3', '#' %></li>
</ol>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#employees_select').change(function() {
$.ajax({
url: "<%= update_employee_movements_path %>",
data: { employee_id : $('#employees_select').val() },
dataType: "script"
});
});
$('#commendations_click').click(function() {
$.ajax({
url: "<%= commendations_path %>",
data: {
employee_id : $('#employees_select').val(),
employee_movement_id : $('#employee_movements_select').val()
},
dataType: "script"
});
});
});
</script>
app/controllers/reports_controller
class ReportsController < ApplicationController
before_filter :authenticate_user!
# GET /reports
def index
#employees = Employee.all
#employeemovements = EmployeeMovement.distinct_positions
end
def update_employee_movements
if params[:employee_id]
#employeemovements = [].insert(0, "Select Employee Movement")
else
employee = Employee.find(params[:employee_id])
#employeemovements = employee.employee_movements.map{ |a| [a.position, a.id] }.insert(0, "Select Employee Movement")
end
end
def commendations
emdates = EmployeeMovement.last_2_dates_obtained(params[:employee_movement_id])
date_from = emdates[0].date_obtained
date_to = emdates.length == 1 ? nil : emdates[1].date_obtained
emp = Employee.find(params[:employee_id])
#commendations = case date_to.nil?
when true then emp.commendations.this_day_onwards(date_from)
else emp.commendations.within(date_from, date_to)
end
end
end
What I'm trying to do here is, I'm creating a page filled with links and drop down lists that will serve as a Reports center. The idea is, each link will be catered by a controller. Each controller will be responsible in showing my PDF in the browser (through ThinReports, if you're curious).
The #employees_select change event is used for changing the value of the #employee_movements_select collection_select.
Now my problem is, how can i capture the value of both #employees_select and #employee_movements_select and pass them to my commendations action?
I tested link_to by hardcoding values, and it works (code below)
<%= link_to 'COMMENDATION', commendations_path(employee_id: 1, employee_movement_id: 12, format: 'pdf') %>
However, If I use javascript to push the values to my commendations action through the 'click' event, my commendations action will be called twice, thus an error occurs because the params[:employee_id] in the action is now blank.
By the way, I need those values because my commendations action needs it so I can populate my PDF report template.
Please help. Thanks a lot in advance!
UPDATE 1
-> Updated link_to:
<%= link_to 'COMMENDATION', '#', { id: 'commendations_click' } %>
-> Removed dataType: "script" in #commendations_click event handler
-> Updated url: in #commendations_click event handler
url: <%= commendations_path(format: 'pdf') %>
UPDATE 2 (RESOLUTION)
I tweaked my javascript to look something like this:
$('#commendations_click').click(function() {
event.preventdefault();
window.location = "<%=j commendations_path(format: 'pdf') %>" + "?employee_id=" + $('#employees_select').val() + "&employee_movement_id=" + $('#employee_movements_select').val();
});
Works perfect now.

Two things come to mind. You can wrap the two select lists within a form element and just do a submit. Everything inside the form will be submitted to your server and you can process the request and handle the redirect on the server side. The other thing you can do is to handle the commendations click event on the client side using jquery or something. Just bind to the click event of that link, grab the values of the two select lists and do whatever you want with it. Remember, link_to just gets rendered as plain old html links on the view. For e.g.
link_to "Profile", profile_path(#profile) gets rendered as Profile

Related

How to send a selected element and a text input via jQuery

My app has a live search implemented and it works properly. The problem that I have is that now I have a table with a lot of columns and I want to search through all elements. I want to have only one text input and a drop down that will select the column that I want to search in.
Searchable module
module Searchable
extend ActiveSupport::Concern
module ClassMethods
def search_for(present_column,record)
record.present? ? where(present_column+' LIKE ?', record+"%") : all
end
end
end
People controller
class PeopleController < ApplicationController
def index
#people = Person.page(params[:page]).per(5).search_for(params[:object_columns], params[:search])
end
The search engine
<%= form_tag do %>
<% valid_column_names = target.column_names.reject{|r| r == "created_at" || r == "updated_at" || r == "slug"} %>
<%= select_tag :object_columns, options_for_select(valid_column_names) %>
<%= text_field_tag :search, '', autocomplete: :off %>
<% end %>
The live search js
$(function () {
$("input#search").keyup(function () {
$.get($("#object_columns option:selected").text(), $("#object_columns").serialize(), null, "script");
$.get($("#search").attr("action"), $("#search").serialize(), null, "script");
});
});
The input text is returned as expected, but nothing comes from the object_columns. When I type the word "n", for example, my server terminal returns this message:
Started GET "/people?&search=n&_=1463081307356" for 127.0.0.1 at 2016-05-12 16:28:34 -0300
Processing by PeopleController#index as JS
Parameters: {"search"=>"n", "_"=>"1463081307356"}
EDIT:
I had an idea later on and made some changes. I gave the form an ID and used it to do the request, now I can have both information (column names and the search record) at the same time. The only problem now is with the path, it is returning an URI error.
The search engine
<%= form_tag people_path, class: "form_id" do %>
<% valid_column_names = target.column_names.reject{|r| r == "created_at" || r == "updated_at" || r == "slug"} %>
<%= select_tag :object_columns, options_for_select(valid_column_names) %>
<%= text_field_tag :search, '', autocomplete: :off %>
<% end %>
The live search
$(function () {
$("input#search").keyup(function () {
$.get($(".form_id"), $(".form_id").serialize(), null, "script");null, "script");
});
});
In your search_for method, the return value is always all. You really want the return value to be the result of the ternary operator directly above it. Remove the last all and you should be good to go.
module ClassMethods
def search_for(present_column,record)
record.present? ? where(present_column+' LIKE ?', record+"%") : all
# all <== this should be removed
end
end
In your javascript, you'll need a few changes:
$(function () {
function search() {
$.get("/search", { column_name: $("select#column_name").val(), search: $("#search").val() }, null, "script");
};
$("select#column_name").change(search);
$("input#search").keyup(search);
});
The actual Ajax call has been changed to:
remove the undefined "action" attribute on the search input field
explicitly reference the URL to send the request
create hash parameters for the ajax call
remove the unnecessary calls to serialize()
This also installs a handler on the change event of the column selection, hence the refactoring of the Ajax call to a separate function.

Rails 4: How do I do an AJAX call on nested forms?

I'm trying to set up my form so that when the user changes the "position" drop down box selection it will update a partials with records that are related to that position. I will do my best to include all relevant code below with the error shown first. If I've forgotten to include anything please let me know, thanks.
Error (from the... jqXHR.responseText)
AJAX Error: NameError in Players::Reports#update_position_specifics
Showing ../app/views/players/reports/update_position_specifics.js.erb where line #2 raised:
undefined local variable or method `f' for #<#<Class:0x007f9b82ebdcf8>:0x007f9b82fc8030>
reports.coffee
$(document).on 'change', '#report_position_id', (evt) ->
$.ajax 'update_position_specifics',
type: 'GET'
dataType: 'script'
data: {
position_graded_id: $("#report_position_id option:selected").val()
}
error: (jqXHR, textStatus, errorThrown) ->
console.log("AJAX Error: #{jqXHR.responseText}")
success: (data, textStatus, jqXHR) ->
console.log("Dynamic position select OK!")
_form.html.erb
<%= simple_form_for([#player, #report], html: {id: 'report-form'}) do |f| %>
<%= f.association :position, selected: #position_graded.id %>
<div id="position_specifics">
<%= render 'form_position_specifics', f: f %>
</div>
<% end %>
_form_position_specifics.html.erb
<%= f.nested_fields_for :evaluations,
f.object.evaluations.target.sort_by! { |a| a.skill.order_by },
wrapper_tag: :tr, wrapper_options: { class: 'fields' } do |fn| %>
<% # Form fields here... %>
<% end %>
update_position_specifics.js.erb
$("#position_specifics").empty().append("<%= escape_javascript(render partial: 'form_position_specifcs', f: f") %>")
reports_controller.rb
def update_position_specifics
# remove previous/existing position specific skill from evaluations
#report.evaluations.joins(:skill).where(skills: { type: 'position specifcs'}).delete_all
# add new position specifics from specified position
#skills = Skill.joins(:positions).where(position_id: #position_graded.id)
# Add new evaluations to report
#skills.joins(:positions).where(positions: {id: #position_graded_id}, disabled: false).each do |skill|
#report.evaluations << Evaluation.new(skill_id: skill.id
end
end
Updated Answer
views/posts/new.html.erb
<%= form_for(#post, id: 'myform') do |f| %>
<%= f.association :pictures do |ff| %>
<% target = "picture-#{ff.object.id}-div-that-will-updated" %>
<%= ff.select :category, 'data-target': target %>
<%= ff.file_field :file %>
<!-- This is the element that will be updated when <select> above is changed -->
<div id='<%= target %>'></div>
<% end %>
<% end %>
javascripts/posts/new.js
$('#myform').find('select').change(function() {
// get the data-target of the <select>, then load that target element with the new partially loaded (current url) target element
$( '#' + $(this).attr('data-target') )
.load( window.location.href + ' #' + $(this).attr('data-target') );
// Take note of the space in ' #' above
}
In summary, what this all will do is when a user selects from a dropdown, the page is just reloaded. But instead of reloading the whole page, only the data-target element is updated. This also works for multiple nested associated records on the page.

How to return a selected value from a database collection in Rails?

So I have a database collection labeled #joe, and I am trying to pass the id variable into a link url path. This is in my index.erb.html file.
<%= select_tag "article", options_from_collection_for_select(#joe, 'id', 'title'),
prompt: "Select Something" %>
In my articles_controller.rb file, I have
def index
#joe = Article.all
end
I made a loop where it grabs each id number and passes it into the article_url path. I was wondering, in the dropdown box that I created above, when I select a certain value, I want to pass that value into the article.id variable. I'm having trouble with this and it outputs x amount of buttons.
<% #joe.each do |article| %>
<%= button_to "SELECT", article_url(article.id), :method => 'get' %>
<% end %>
I was wondering if it is possible to do this or if I can implement JavaScript or jQuery into this. Any help would be appreciated. Thank you!
And here's the rake routes command results:
Prefix Verb URI Pattern Controller#Action
home_index GET /home/index(.:format) home#index
articles GET /articles(.:format) articles#index
POST /articles(.:format) articles#create
new_article GET /articles/new(.:format) articles#new
edit_article GET /articles/:id/edit(.:format) articles#edit
article GET /articles/:id(.:format) articles#show
PATCH /articles/:id(.:format) articles#update
PUT /articles/:id(.:format) articles#update
DELETE /articles/:id(.:format) articles#destroy
root GET / home#index
Let's try this:
ERB
<%= form_tag article_path do %>
<%= select_tag "id", options_from_collection_for_select(#joe, 'id', 'title'), prompt: "Select Something", class: 'select' %>
<%= button_tag 'SELECT', class: 'button' %>
<% end %>
JS
$('.button').on('click', function() {
var path = $('form').attr('action');
var articleId = $('.select').val();
$.get([path, articleId].join('/'));
});

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.

javascript how to bind changes of multiple form fields into the same function?

I'm using Ruby on Rails to populate a database from a form that has multiple input text or select fields. I'm using AJAX so that every time the user makes a change in any input field, all input fields values are automatically taken into account and some other result fields get refreshed.
Everything works fine with the following script for the 1st 2 input fields, but I'm planning to have 50+ input fields if not more, and I wonder if there is a smarter way to implement my script without explicitly defining a separate function for each field.
I'd appreciate any idea how to scale my script without repeating the same thing 50+ times?
This is my js
<script type="text/JavaScript">
$(function(){
$('.input_1_class').bind('change', function(){
$.ajax({
url: "<%= update_fields_projects_url %>",
data: {
input_1: $('.input_1_class').val(),
input_2: $('.input_2_class').val(),
}
});
});
$('.input_2_class').bind('change', function(){
$.ajax({
url: "<%= update_fields_projects_url %>",
data: {
input_1: $('.input_1_class').val(),
input_2: $('.input_2_class').val(),
}
});
});
});
</script>
and this is my Ruby form (simplified)
<%= form_for(#project, :html => {:name => "ProjectInfo"}) do |f|
field_set_tag "Customer Information" do %>
<div class="field">
<%= f.label :"Input 1" %>
<%= f.text_field :Input_1, {:class=>"input_1_class"} %>
<%= f.label :"Input 2" %>
<%= f.text_field :Input_2, {:class=>"input_2_class"} %>
<%= f.label :"Output 1" %>
<%= f.text_field :Output_1, {:id=>"output_1_id"} %>
</div>
<% end %>
<% end %>
Why not just do something like:
$("form input").bind("change", function() {
var $form = $(this).closest("form");
var data = {};
$.each($form.serializeArray(), function(i, v) { data[v.name] = v.value; });
$.ajax({
url: $form.data('refresh'),
data: data
});
});
And your form needs the data-refresh property:
<%= form_for(#project, :html => {:name => "ProjectInfo", :data => {:refresh => update_fields_projects_url}}) do |f|
That way, your AJAX event handler doesn't have to have specific knowledge of the form it's operating on - you just bind it to a form with a data-refresh attribute and it'll post the form's data to that URL whenever a field in the form changes.
You can specify multiple selectors, and have the same event bound to all of them:
$('.input_1_class, .input_2_class').click(function ()
{
alert('Bound to both inputs');
});

Categories

Resources