Hi I am making a ajax call
$(function () {
$('.pagination a').click(function () {
$.get(this.href, null, null, "script");
return false;
});
});
I thought that the last argument of $get would ensure that response is rendered as Javascript but it is being processed as HTML. I don't understand why.
My controller index action:
def index
#accounts = Account.paginate(:page => params[:page], :per_page => 10)
end
My in index.js.erb
alert("This is an AJAX request.");
the log:
Started GET "/admin/accounts?page=2&_=1415008178615" for 127.0.0.1 at 2014-11-03 09:50:01 +0000
Processing by Admin::AccountsController#index as HTML
Parameters: {"page"=>"2", "_"=>"1415008178615"}
and then ends with
Rendered admin/accounts/_accounts.haml (207.1ms)
Rendered admin/shared/_content_card.html.haml (210.7ms)
Rendered admin/accounts/index.haml within layouts/admin (364.1ms)
Big thanks to all who tried to answer this question. The problem turned out to be in config/routes.rb
namespace :admin, :defaults => { :format => "html" } do
this line defaulted all the requests to be processed as HTML and after removing the default, and adding the following code to the index action in the controller, it all works perfectly.
respond_to do |format|
format.html
format.js {render :layout => false }
end
Jquery ajax response rendered as HTML instead of JS
This could be due to a number of things. The href of anchor tag is same as the url for ajax request so i think your js function is not being called at all and It's sending an html request because that's what a link does by default. To check if it's calling your js function or not you can use a simple console.log or alert statements inside your js function and check if they are being fired. Also if you are using turbolinks then you should try to use jquery on function. Try something like this:
$(document).on("click",".pagination a", function(e){
e.preventDefault();
$.get(this.href, null, null, "script");
})
Edit:
If get function isn't working then try the verbose ajax method of jquery
$(document).on("click",".pagination a", function(e){
e.preventDefault();
var url = $(this).attr('href');
$.ajax({
type: "GET",
url: url,
dataType: "script"
});
})
OR
If that doesn't work either then instead of calling ajax method by js just use remote option of link_to and it'll dry up your code as well
= link_to "some anchor", some_route_path, remote: true
Try to change type of dataType(last argument) to JSON
$(function () {
$('.pagination a').click(function () {
$.get(this.href, null, null, "json");
return false;
});
});
From here:
http://api.jquery.com/jQuery.get/
dataType
Type: String
The type of data expected from the server. Default: Intelligent Guess (xml, json, script, or html).
EDIT:
This can be error with your RAILS server. You need to explicitly tell rails route to render json. Otherwise it renders html templates.
So, if you cange your backend code to this:
def index
#accounts = Account.paginate(:page => params[:page], :per_page => 10)
render json: #acounts
end
the result would be JSON
EDIT2:
So, if you are trying to get script, you can try http://api.jquery.com/jQuery.getScript/
$.getScript(url, successCallback);
Related
I am trying to send data through a get request using ajax but the param doesn't seem to be getting sent. I have a page that shows a random item from the db. You get to this page from a link in the navbar. Once on this page there is a link that allows you to skip the current item to find another random item making sure the next item isn't the one the user was just viewing.
routes.rb
get 'pending', to: 'items#pending'
view
<%= link_to 'Skip', '', class: "btn btn-default btn-xs",
id: "skip-btn",
:'data-item-id' => #pending_item.id %>
controller
def pending
#previous_pending_item_id = params[:id] || 0
#pending_items = Item.pending.where("items.id != ?", #previous_pending_item_id)
#pending_item = #pending_items.offset(rand #pending_items.count).first
respond_to do |format|
format.js
format.html
end
end
I have respond to both html and js because I am using the action for the navbar link as well as the link on the page. The link on the page is the skip button which should bring up another random item.
sitewide.js.erb
$('#skip-btn').on('click', function () {
$.ajax({
data: {id: $(this).data("item-id")},
url: "/pending"
});
});
When I look in the server log is says Started GET "/pending"... but doesn't make any mention of a param being sent. What am I missing?
The reason I'm using ajax for this is because I don't want the param showing in the url.
For clarification I need the url when visiting this page to always be /pending with no params or additional :id identified in the url. This page should always show a random record form the db. The only reason I need to send a param is to make sure no record is every repeated consecutively even though they are random.
I think you need to prevent default link action:
$('#skip-btn').on('click', function (event) {
event.preventDefault();
...
});
While you can do it the way you're attempting, I think it's worth pointing out that sending data in a GET request is a bit of an antipattern. So why not doing it the "correct" way!
Change your routes.rb to:
get 'pending/:id', to: 'items#pending'
and change sitewide.js.erb to:
$('#skip-btn').on('click', function () {
$.ajax({
url: "/pending/" + $(this).data("item-id")
});
});
I'd like you to check for the format its sending the the query to your controller. And the type of format you want to receive at the front end.
$('#skip-btn').on('click', function (e) {
e.preventDefault();
$.ajax({
dataType: 'json', //This will ensure we are receiving a specific formatted response
data: {id: $(this).data("item-id")},
url: "/pending"
});
});
In your controller maybe you want to pass it back as a json object.
def pending
##previous_pending_item_id = params[:id] || 0
#No need to make it an instance variable
previous_pending_item_id = params[:id] || 0
#Same goes for pending_items. No need to make it a instance variable, unless you're using it somewhere else.
pending_items = Item.pending.where("items.id != ?", previous_pending_item_id)
#pending_item = pending_items.offset(rand pending_items.count).first
respond_to do |format|
format.js
format.html
format.json { render json: #pending_item.as_json }
end
end
So that you can take value from response and append it to your page.
Similarly if you are expecting a js or html response back, you should mention that in your ajax call. Let me know if it does help you resolve your issue.
Update:
Let's say in your page, it shows the data of #pending_item object in a div,
<div id="pending_item">...</div>
When you're making a ajax request to your controller you want div#pending_item to show the a new random pending_item.
$('#skip-btn').on('click', function (e) {
e.preventDefault();
$.ajax({
dataType: 'html', //we'll receive a html partial from server
data: {id: $(this).data("item-id")},
url: "/pending",
success: function(res){
//We'll set the html of our div to the response html we got
$("#pending_item").html(res);
}
});
});
In your controller you do something like:
format.html { render partial: 'pending_item', layout: false }
And in your partial file "_pendint_item.html.erb" you'll access your instance variable #pending_item and display data
This will send the response to server as html, and there you'll only set your div's html to this.
Update 2
Your partial might look like this, or just however you want to display your pending item. The thing to know is it will be accessing the same instance variable #pending_item you have defined in your controller's method, unless you pass locals to it.
<div class="pending_item">
<h3><%= #pending_item.name %></h3>
<p><%= #pending_item.description %></p>
</div>
I suggest you do a console.log(res) in the success callback of your ajax call to see what you're getting back from server.
I'm attempting to use Ajax with Ruby on Rails 4 to watch when the checkbox changes and submit the form and save the checkbox change to the database. Even with the debugger I'm not seeing any errors. Any thoughts?
I recently changed the path to edit because I was getting a 404. I did this to it matches a route.
I just added the success function to the ajax call and it appears to be firing.
This is what I have currently:
This is product_controller
def update
if #product.update(safe_params)
redirect_to [:edit, #product], flash: { notice: t('shoppe.products.update_notice') }
else
render action: 'edit'
end
end
This is form in haml
= form_for product, :remote => true do |f|
= f.check_box :active
= f.label :active, t('shoppe.products.active'), :remote => true
This is js:
$('#product_active').bind('change', function() {
console.log('changed');
var action = $(this).parents('form').attr('action')+"/edit";
var method = "GET";
var checked = $(this).attr('checked');
var data = $(this).attr('value');
data ^= 1;
$.ajax({
method: method,
url: action,
data: checked,
success: function() {
alert("AJAX Fired");
}
})
debugger;
});
This is from rake routes
products GET /products(.:format) shoppe/products#index
POST /products(.:format) shoppe/products#create
new_product GET /products/new(.:format) shoppe/products#new
edit_product GET /products/:id/edit(.:format) shoppe/products#edit
product GET /products/:id(.:format) shoppe/products#show
PATCH /products/:id(.:format) shoppe/products#update
PUT /products/:id(.:format) shoppe/products#update
DELETE /products/:id(.:format)
UPDATE: I ended up putting a hidden submit button with the form and changing my js to and adding in a class to the form to allow me to hit all ajax with one set of code:
$('.ajax').bind('change', function() {
$(this).parents('form').submit();
});
You need to hit the update endpoint of your routes not the edit. The edit route is usually to load the edit view.
You'll also want to return a json encoded response in the update action and handle the success jquery callback and from there you would redirect in the client side or do whatever you want to do to update the UI. A redirect would be only useful from within your rails code if you were actually submitting a form and not doing ajax.
This is my "link":
%span{:id => "car_#{car.id}", :onclick => "add_car(#{car.id}"} Add
that leads on to here:
function add_trending(car_id) {
jQuery.ajax({
url: "/cars/add_car",
type: "GET",
data: {"car_id" : car_id},
dataType: "html"
});
}
in controller:
def add_car
#car = Car.find(params[:car_id])
...
respond_to do |format|
format.js
end
end
and add_car.js.erb:
alert("YES");
But the alert window is not popped up. When I take a look at logs, I see there following:
Rendered cars/add_car.js.erb (0.0ms)
The javascript is just rendered, not executed based on logs. How is that possible?
Thanks
If your ajax request returns javascript you must set the dataType : script or use $.getScript function.
In this case you haven't any success callback function.
Have you looked at your network traffic client-side? I'm guessing that you're sending this down to the client, but it doesn't know what to do with this result. In fact, if that's your entire handler in jQuery, then it won't do anything with the response. You need a success and/or failure handler in the options object passed to jQuery.ajax, or you need to attach one to the promise it returns. In other words, you're probably getting the data back but not doing anything with it.
Is it possible to call a javascript function from a controller in rails?
What I do is to make a Rails controller produce a javascript action. Is have it call a partial that has javascript included in it.
Unless you want that activated on page load, I would set it up via AJAX. So that I make an AJAX call to the controller which then calls a javascript file.
This can be seen via voting :
First the AJAX
//This instantiates a function you may use several times.
jQuery.fn.submitWithAjax = function() {
this.live("click", function() {
$.ajax({type: "GET", url: $(this).attr("href"), dataType: "script"});
return false;
});
};
// Here's an example of the class that will be 'clicked'
$(".vote").submitWithAjax();
Second the Controller
The class $(".vote") that was clicked had an attribute href that called to my controller.
def vote_up
respond_to do |format|
# The action 'vote' is called here.
format.js { render :action => "vote", :layout => false }
end
end
Now the controller loads an AJAX file
// this file is called vote.js.haml
== $("#post_#{#post.id}").replaceWith("#{ escape_javascript(render :partial => 'main/post_view', :locals => {:post_view => #post}) }");
You have successfully called a javascript function from a controller.
No, but you could output javascript that would be called immediately in your view e.g.
<script type="text/javascript">
function IWillBeCalledImmediately()
{
alert('called');
};
IWillBeCalledImmediately();
</script>
However it would probably be better to use jquery and use the ready event.
<script type="text/javascript">
$(function() {
alert('called');
});
</script>
I have a following code that is part of the _form.html.erb code. Basically I have a form in which I have a observe_field function where on change, it will set fields' values without refreshing the page. Following is my html code:
<script type="text/javascript">
// When DOM loads, init the page.
$(function() {
// Executes a callback detecting changes with a frequency of 1 second
$("#id_element_placeholder").observe_field(1, function( ) {
$.ajax({
type: "GET",
dataType: "json",
url: "/students/get/" + this.value,
success: function(data){
$('#last_name').attr('value', data.student.last_name);
$('#building').attr('value', data.student.building);
$('#room').attr('value', data.student.room);
}
});
});
});
</script>
Problem here is that I'm exposing lot of my code in javascript. Is there a better way to do it without exposing code in javascript?
Here is what my controller looks like:
def get
#student = Student.find(params[:id])
respond_to do |format|
format.html
format.json { render :json => #student }
end
end
Basically I get an id in a form and from there I have to get the corresponding object and update the fields on the page.
Assuming your design requires you to make AJAX calls to query student info by id, then you need to expose a URL for the call. If you don't want to expose a JSON data structure, you could return a chunk of HTML (instead of JSON), and replace the contents of the container of all of the controls you mention above.