link_to doesnt replace div's content - javascript

the relevant controller code:
def show_host
queue = TestQueue.find(params[:id])
#test_queues = TestQueue.where(:host => queue.host)
respond_to do |format|
format.html { render action: "show_host", :layout => nil}
format.json { render json: #test_queue }
end
end
view:
<iframe name="host_queues", scrolling="yes" width="82%" height="700px", align="right", frameborder="0", rel="stylesheet"></iframe>
<%= link_to host, { :controller => "test_queues", :action => "show_host", :id => id}, {:target => "host_queues"} %>
now the thing is, it works with replace the content of the iframe, but when i try to replace content in a div with class="host_queues", it doesnt work... works only with iframe ..
can any1 out a finger on the reason ? 10x ..

target only applies to frames and windows. You have to use Javascript to replace the contents of a div.

use remote: true option in link_to and than write javascript
OR
use form_tag with remote: true, in update option, give div id which you want to replace
you can chek below link
http://guides.rubyonrails.org/working_with_javascript_in_rails.html

Related

How to use Javascript and AJAX to render popup on index page Ruby on Rails 5

I have a simple inventory system application I've been developing for a class project. One of the requirements is to have some form of Javascript and AJAX doing something in the app. It doesn't have to be anything large or super complicated, but it does have to be there. What my group decided to do was render a popup that displays information about an item when you click on the 'show' link, as it was similar to an example the professor did in class and it was somewhat useful for our app as well. However I cannot get it to work, it just bypasses the ajax and javascript stuff and goes straight to the show.html.haml page. Here is my code:
index.html.haml
%p#notice= notice
%h1 Items
%table
%thead
%tr
%th Name
%th Description
%th Quality
%th Price
%th Location
%th Options
%tbody
- #items.each do |item|
%tr
%td= item.name
%td= item.description
%td
= item.quality
%br/
%br/
= item.quality_desc
%td= item.price
%td= item.location
%td{:colspan => "3"}
= link_to 'Show', item, class: "items"
= link_to 'Edit', edit_item_path(item)
= link_to 'Destroy', item, method: :delete, data: { confirm: 'Are you sure?' }
%br/
= link_to 'New Item', new_item_path
_item.html.haml
This is the information that the popup is supposed to display
%h1 Items
%h2
= item.name
, #{item.category}
%br/
- item.images.each do |image|
= image_tag(image.small.url)
%br
Price: $#{item.price}
%br/
Description: #{item.description}
%br/
Quality: #{item.quality},
\#{item.quality_desc}
%br/
Location: #{item.location}
%br/
%br/
%br/
= link_to 'Edit', edit_item_path(#item)
= link_to 'Close', '', id: 'closeLink'
items_controller.rb
class ItemsController < ApplicationController
before_action :set_item, only: [:show, :edit, :update, :destroy]
# GET /items
# GET /items.json
def index
#items = Item.all
end
# GET /items/1
# GET /items/1.json
def show
render(:partial => 'item', :object => #item) if request.xhr?
end
# GET /items/new
def new
#item = Item.new
end
# GET /items/1/edit
def edit
end
# POST /items
# POST /items.json
def create
#item = Item.new(item_params)
respond_to do |format|
if #item.save
format.html { redirect_to #item, notice: 'Item was successfully created.' }
format.json { render :show, status: :created, location: #item }
else
format.html { render :new }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /items/1
# PATCH/PUT /items/1.json
def update
respond_to do |format|
if #item.update(item_params)
format.html { redirect_to #item, notice: 'Item was successfully updated.' }
format.json { render :show, status: :ok, location: #item }
else
format.html { render :edit }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /items/1
# DELETE /items/1.json
def destroy
#item.destroy
respond_to do |format|
format.html { redirect_to items_url, notice: 'Item was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_item
#item = Item.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def item_params
params.fetch(:item, {}).permit(:name, :description, :quality, :quality_desc, :price, :location, :category, { images: [] })
end
end
items.js
var ItemPopup = {
setup: function() {
// add hidden 'div' to end of page to display popup:
var popupDiv = $('<div id="itemInfo"></div>');
popupDiv.hide().appendTo($('body'));
$(document).on('click', '#items a', ItemPopup.getItemInfo);
},
getItemInfo: function() {
$.ajax({type: 'GET',
url: $(this).attr('href'),
timeout: 5000,
success: ItemPopup.showItemInfo,
error: function(xhrObj, textStatus, exception) {alert('Error!'); }
//'success' and 'error' functions will be passed 3 args
});
return(false);
},
showItemInfo: function(data, requestStatus, xhrObject) {
//center a floater 1/2 as wide and 1/4 as tall as screen
var oneFourth = Math.ceil($(window).width() / 4);
$('#itemInfo').css({'left': oneFourth, 'width': 2*oneFourth, 'top': 250}).html(data).show();
//make the Close link in the hidden element work
$('#closeLink').click(ItemPopup.hideItemInfo);
return(false); //prevent default link action
},
hideItemInfo: function() {
$('#itemInfo').hide();
return(false);
}
};
$(ItemPopup.setup);
application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
// require turbolinks
// require_tree .
//= require items
application.html.haml
!!!
%html
%head
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
%title InventoryManager
= csrf_meta_tags
// = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'
// = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
= stylesheet_link_tag 'application'
= javascript_include_tag "application"
%body
%nav.navbar.navbar-default
.container-fluid
/ Brand and toggle get grouped for better mobile display
.navbar-header
%button.navbar-toggle.collapsed{"aria-expanded" => "false", "data-target" => "#bs-example-navbar-collapse-1", "data-toggle" => "collapse", :type => "button"}
%span.sr-only Toggle navigation
%span.icon-bar
%span.icon-bar
%span.icon-bar
%a.navbar-brand{:href => "/default/index"} InventoryManager
/ Collect the nav links, forms, and other content for toggling
#bs-example-navbar-collapse-1.collapse.navbar-collapse
%ul.nav.navbar-nav
%li.active
%a{:href => "#"}
Items
%span.sr-only (current)
%ul.nav.navbar-nav.navbar-right
- if admin_signed_in?
%li= link_to "Logout", destroy_admin_session_path, :method => :delete
- elsif employee_signed_in?
%li= link_to "Logout", destroy_employee_session_path, :method => :delete
- else
%li
%a{:href => "/admins/sign_in"} Admin
%li
%a{:href => "/employees/sign_in"} Staff
/ /.navbar-collapse
/ /.container-fluid
= yield
If you need anymore of the code just ask. This is in Ruby on Rails 5
EDIT: So I fixed it by changing the selector in the event handler function so that it read '#items' and it grabbed the elements on my page with that id. However I got the code I was trying to use originally from a textbook, implying that what was there was supposed to work. Can someone explain to me why it didn't work initially?
EDIT2: Nevermind I figured it out.
So it turns out my trouble was this line right here:
$(document).on('click', '#items a', ItemPopup.getItemInfo);
I got this code from my class's textbook and modified it slightly to fit my application. As a result of this and a lack of knowledge of how the selectors worked, I thought this was selecting anchor tags with an id of 'items'. As it turns out, what it was actually doing is getting all the anchor tags inside an element with an id of 'items', in the case of the book, this particular element was a table, and the only links inside that table went to that applications show.html.haml page. That didn't quite work for my app since the index table has 3 different types of links on it, so I changed the line to read
$(document).on('click', '.items', ItemPopup.getItemInfo);
and changed the 'show' links on my index.html.haml to have a class of 'items'. This fixed my problem and it works perfectly now.
That being said if there is a solution to this sort of problem that is considered a better practice feel free to share it as an answer to this proble, as well, I'm all for learning something new.

Rails Ajax Refresh Partial while persisting params

I have a Rails app with a controller/view called "calls". Here is the basic controller action for index:
calls_controller.rb
def index
if params[:region].present?
#assigned = Call.where(region_id: params[:region][:area]).assigned_calls.until_end_of_day
#unassigned = Call.where(region_id: params[:region][:area]).unassigned_calls.until_end_of_day
else
#assigned = Call.assigned_calls.until_end_of_day
#unassigned = Call.unassigned_calls.until_end_of_day
end
end
Here are my views:
index.js.erb
$('#active').html("<%= escape_javascript render :partial => 'calls/assigned_calls', :locals => {:assigned_calls => #assigned} %>");
$('#inactive').html("<%= escape_javascript render :partial => 'calls/unassigned_calls', :locals => {:unassigned_calls => #unassigned} %>");
$(".select").select2({
placeholder: "Select One",
allowClear: true
});
index.html.erb
<div id="active">
<%= render "assigned_calls" %>
</div>
<div id="inactive">
<%= render "unassigned_calls" %>
</div>
<script>
$(document).ready(function() {
setInterval(function () {
$.ajax('calls/<%= params[:region][:area] %>');
} , 5000);
});
</script>
_assigned_calls.html.erb (view code omitted)
<%= form_tag calls_path, :method => 'get' do %>
<p>
<%= select_tag "region[area]", options_from_collection_for_select(Region.order(:area), :id, :area, selected: params[:region].try(:[], :area)), prompt: "Choose Region" %>
<%= submit_tag "Select", :name => nil, :class => 'btn' %>
So what's happening is on page load if I do not have the params of :region passed it sets the calls without being scoped by region. If region_id is present then it scopes calls where region_id is "1" or whatever the Region ID is that is passed from the submit_tag.
This works fine in the controller and view, however here's my problem. My index.html.erb I need to refresh the partials WITHOUT disturbing the params passed. So on setInterval I need to figure out how to reload the partials while persisting the params passed in the URL.
I tried to figure this out using a setInterval method but I'm not sure what I'm doing here 100%.
Can someone give me some advice on how to refresh the partials every 5 seconds while persisting the params so my instance variables persist through refresh?
If you need more context and/or code please let me know.
Update
Trying to rework the javascript based off an answer from a user and here's what I have.
<script>
$(document).ready(function() {
setInterval(function () {
$.ajax({
url: 'calls_path',
type: "GET",
data: { "region": '<%= #region.html_safe %>' }
}), 5000);
});
});
</script>
The page will load but when it tried to trigger in the chrome inspector I get:
calls?utf8=✓&region[area]=3:2901 Uncaught SyntaxError: Unexpected token )
Maybe this is a JS syntax error or I'm not closing the function properly.
If I understood properly, you want to have your parameters somehow pipelined through AJAX call to your controller, back to your js.erb file where it refreshes the partials?
My advice is to set passed parameters as instance variables in your controller like this:
calls_controller.rb
def index
if params[:region].present?
#region = params[:region]
#assigned = Call.where(region_id: params[:region][:area]).assigned_calls.until_end_of_day
#unassigned = Call.where(region_id: params[:region][:area]).unassigned_calls.until_end_of_day
else
#assigned = Call.assigned_calls.until_end_of_day
#unassigned = Call.unassigned_calls.until_end_of_day
end
end
Now your #region instance variable will be available in your index.js.erb
where you can pass it to other partials you are trying to render.
index.js.erb
$('#active').html("<%= escape_javascript render :partial => 'calls/assigned_calls', :locals => { :assigned_calls => #assigned, :region => #region } %>");
$('#inactive').html("<%= escape_javascript render :partial => 'calls/unassigned_calls', :locals => { :unassigned_calls => #unassigned, :region => #region } %>");
_assigned_calls.html.erb
<%= form_tag calls_path, :method => 'get' do %>
<%= select_tag "region[area]", options_from_collection_for_select(Region.order(:area), :id, :area, selected: region.try(:[], :area)), prompt: "Choose Region" %>
<%= submit_tag "Select", :name => nil, :class => 'btn' %>
<% end %>
Also, I think that better practice in your index.html.erb script tag
is to do it like this:
<script>
$(document).ready(function() {
setInterval(function () {
$.ajax({
url: 'calls_path',
type: "GET",
data: { "region": '<%= #region.html_safe %>' }
});
}, 5000);
});
</script>
Please test this out if you're interested and get back to me :)

link_to no route matches only after AJAX create of a post

Basically every time I create a post with AJAX, it won't render the new post because of this line:
<%= link_to "promote", vote_scribble_path(:scribble_id => scribble.id, :vote => true), remote: true, method: :post%>
THE LINK ABOVE ACTUALLY WORKS, it just prevents ajax render of newly created post.
here is the error that i get when trying to create new post with AJAX, it does actually create the post and it would render new post without the line above. After refresh of a page the new post with a working link appear.
Rendered scribbles/_scribbles.html.erb (18.9ms)
Rendered scribbles/create.js.erb (19.7ms)
Completed 500 Internal Server Error in 48ms
ActionController::RoutingError - No route matches {:action=>"vote", :controller=>"scribbles", :scribble_id=>155, :vote=>true}:
Here is the full code in action:
create.js.erb updates posts list after create
/*Replace the html of the div post_lists with the updated new one*/
$("#posts_list").html("<%= escape_javascript( render(:partial => "scribbles/scribbles") ) %>");
feedlist.html does render all of the posts
<div id="posts_list">
<%=render :partial => 'scribbles/scribbles', :locals => {:scribbles => #scribbles}%>
</div>
scribbles/_scribbles.html that link_to single line prevents ajax render. but it works.
<% #scribbles.each do |scribble| %>
<%= link_to "promote", vote_scribble_path(:scribble_id => scribble.id, :vote => true), remote: true, method: :post%>
<%end%>
even something like this gives me an error
<%= link_to "promote", vote_scribble_path()%>
vote_scribble_path(:scribble_id => scribble.id, :vote => true), remote: true, method: :post, :put,:get %> tried them all still same error
THE LINK WORKS IT JUST DOESN'T RENDER after AJAX CREATE, after page refresh everything is fine. any ideas why ?
resources :scribbles do
member do
post 'vote'
end
end
scribble_controller.rb
def vote
#scribble = Scribble.find(params[:scribble_id])
#vote = params[:vote]
if #vote == "true"
#v = :up
current_user.vote(#scribble, :direction => #v)
else
current_user.unvote_for(#scribble)
end
respond_to do |format|
format.js{}
end
end
You should be passing id instead of scribble_id in your link.
<%= link_to "promote", vote_scribble_path(:id => scribble.id, :vote => true), remote: true, method: :post%>
because as per your defined routes, the generated route for vote action would be:
vote_scribble POST /scribbles/:id/vote(.:format) scribbles#vote
which you can check by running rake routes.
As you can see vote_scribble_path is expecting an id placeholder and not a scribble_id which is why you receive the error as Rails cannot find a matching route in your application for scribbles#vote action with placeholder :scribble_id.

Onload function to call an action to achieve "Save and Print" through javascript

I have a invoice form in which i want to add option to print invoice on form submit. for this i have added a button and made some changes in controller.Here is my code
In invoice form:
<%= form_for #invoice do |f| %>
:
**Invoice fields**
:
<%= f.submit "Save", :name=>"save", :class=>'btn btn-success' %>
<%= f.submit "Save & Print", :name=>"save_and_print", :class=>'btn btn-default' %>
<% end %>
And in my controller i did this:
def create
:
:
if params[:save_and_print]
format.html { redirect_to("/invoices/#{#invoice.id}?save_and_print=1", :notice => 'Invoice has been saved and printed.') }
else
format.html { redirect_to(#invoice, :notice => 'Invoice has been saved.') }
end
end
def show
:
:
respond_to do |format|
format.pdf do
template=Invoice.get_template(#company, "Invoice", params[:dlc])
pdf=InvoicePdf.new(#invoice, view_context, #receipt_vouchers)
send_data pdf.render, :filename=>"#{#invoice.invoice_number}.pdf", :disposition=>"inline", :type=>'pdf'
end
end
end
And here is my link to print pdf:
<%= link_to raw('<i class="icon-print"> </i>'), invoice_path(#invoice, :format => 'pdf'), :target=>"_blank", :title=>"Print" %>
I am thinking to create an onload function to trigger generate pdf link on view page load after form submit. Any help would be appreciated.
The reason why it is not redirecting to invoice view screen is because of this line if params[:save_and_print],it should be if params[:submit] == "save_and_print"
if params[:submit] == "save_and_print" #here
format.html { redirect_to("/invoices/#{#invoice.id}?save_and_print=1", :notice => 'Invoice has been saved and printed.') }
else
format.html { redirect_to(#invoice, :notice => 'Invoice has been saved.') }
end
You should be accessing the value passed to the submit button through giving params[:submit].
I have got a simple solution for my problem. First of all i gave id to my print pdf link and than call that link on page load. Here is my solution :
<%= link_to raw('<i class="icon-print"> </i>'), invoice_path(#invoice, :format => 'pdf', :dlc=>"no"), :class => 'btn btn-white btn-lg', :id=>"print1-inv", :target=>"_blank", :title=>"Print" %>
and script on show.html.erb:
<% if !params[:save_and_print].blank? && params[:save_and_print]=="1" %>
<script>
$(document).ready(function(){
$("#print1-inv")[0].click();
});
</script>
<% end %>
this code works for me.

How to pass param['id'] to the index page

I am trying to render the user detail on index page when user is clicked.
I am having the list of users in index page like
<% #users.each do |user| %>
<%= link_to user.name, '', {:id => user.id, :name => 'user', :remote => true}
<% end %>
In my javascript
$('#mydiv').html("<%= escape_javascript(render(:partial => '/users/show', :locals => {:id => #{params['id']}})) %>"
but I couldn't able to render the user details, because param 'id' is not passing to this page.
How to get this param and render the partial in the index page when user is clicked.
In this case you should review your code a little. You should directly call the show method in your link and edit your controller to have it responding to JavaScript:
View code:
<%= link_to user.name, user_path(user), remote: true %>
Controller code:
def show
#user = User.find(params[:id])
respond_to do |format|
format.html
format.js
end
end
And create a new view called users/show.js.erb
$("#mydiv").html("<%= escape_javascript(render(:partial => '/users/user_show', :locals => {:user => #user})) %>");
This view is calling a partial view where you can render all your user data. This view is called users/_user_show.html.erb
<div class="myuser">
<%= user.name %>
</div>
Hope that helps

Categories