$.ajax request in Rails 4 app doesn't render view - javascript

I'm new to Rails and I'm trying to submit model data to a controller method, from javascxript, and render the list of results...
function submitResults() {
resultURL = "/result";
resultData = JSON.stringify(results);
$.ajax({
type: "POST",
url: resultURL,
data: { results: resultData},
contentType: "application/html",
dataType: "html"
});
The server shows the controller method is executed and the view is rendered...
Started POST "/result" for 127.0.0.1 at 2014-11-14 17:36:32 -0600
Processing by ResultsController#create as HTML
Result Load (0.7ms) SELECT "results".* FROM "results"
Rendered results/index.html.erb within layouts/application (366.0ms)
Completed 200 OK in 4722ms (Views: 408.3ms | ActiveRecord: 1.3ms)
but the browser doesn't render the view. Here's my create method that's triggered by the $.ajax call...
def create
result = Result.new(result_params)
result.save
#results = Result.all
respond_to do |format|
format.html { render :index }
end
end
Why doesn't the browser load the index view?

You ajax call is not doing anything with the response, define callback functions for it. E.g.:
$.ajax({
type: "POST",
url: resultURL,
data: { results: resultData},
contentType: "application/html",
dataType: "html"
}).done(function(response) {
//attach the response somewhere in the DOM.
});
Check the AJAX doc for all callbacks.
BTW, you usually do not want to load a whole html page through an ajax call. Seems like the page you are rendering includes everything (seems to be using the default layout). In such a case, making AJAX calls can have no benefits (and make things harder) and you might want to do the post through an html form.

Related

Issue passing parameter to Rails controller using AJAX

I'm wanting to send a post request from my JavaScript code to my show action in Ruby on Rails which contains data that I want to store in an instance variable so I can save it on a form in my view and upload it to my server.
As you can see below, the parameter 'base64' is showing up in my rails logs, but when I try to call #base64 in my view, after grabbing the value in the controller, it's nil.
Any advice is appreciated, thanks!
View
var full_base64 = "data:image/jpeg;base64," + base64;
$.ajax({
data: 'base64=' + full_base64,
type: 'POST',
url: "/videos/show/<%=#video.id%>"
});
Controller
def show
#video = Video.find(params[:id])
if params[:base64].present?
#base64 = params[:base64]
end
end
Routes
post 'videos/show/:id', to: 'videos#show'
Rails server log:
Started POST "/videos/show/1" for 127.0.0.1 at 2020-01-22 12:59:40 -0600
Processing by VideosController#show as */*
Parameters: {"base64"=>"data:image/jpeg;base64,iV...
...
, "id"=>"1"}
Console
>>
#base64
=> nil
>>
If I understand correctly you are trying to pass AJAX to the show action in your controller. This is a very GENERALIZED answer as you have failed to include any of your HTML code and it looks like you don't have a button to fire the AJAX. But I'll try to point you in the right direction. You need to do something along the general lines of:
var full_base64 = "data:image/jpeg;base64," + base64;
$.ajax({
data: 'base64=' + full_base64,
type: 'POST',
url: "/videos/my_ajax_upload"
});
That will send your AJAX call to a controller method I've called my_ajax_upload but you can call it whatever you like. In your controller you would need something like:
def my_ajax_upload
#video.update(base_64: params[:base64])
respond_to do |format|
format.js {render :action => "base_64_response" }
end
end
This responds to the initial AJAX call by saving the param you sent to the DB and replying by calling a file called base_64_response.js.erb which might look something like:
$('#pic_upload').html('<%= escape_javascript(render :partial => 'base_64_response') %>');
Which will render the HTML file called base_64_response.html.erb which needs to contain the html code you want to appear in the page that called it.
<div id="pic_upload">
<%= #base64 =>
</div>
The cycle is load page -> do something to trigger AJAX call to controller method -> process AJAX call with controller method -> render JS file -> JS file replaces div in page with new html
You probably need to read up more on how AJAX works in Rails. This RailsCast might help http://railscasts.com/episodes/136-jquery-ajax-revised?view=asciicast
Just FYI - I have also noticed strange things in Rails if you do not explicitly define the content type. In your posted example you are not stating the contentType and it could be parsing nil for that reason. When posting base 64 data you can specify the content type as:
$.ajax({
data: 'base64=' + full_base64,
type: 'POST',
contentType: 'application/octet-stream'
url: "/videos/show/<%=#video.id%>"
});
and it may change what the controller parses for the body.
How to post an image in base64 encoding via .ajax?
Just use string instead of symbol for hash key
if params["base64"].present?
#base64 = params["base64"]
end

Receiving 406 (Not acceptable) for AJAX action Rails 4

I'm trying to auto-refresh a single partial view every 60 seconds on the index page. I tried splitting the actions into two routes, so that the JS would be easier to change and manage. It seems to be a problem with the respond_to block, maybe you can help me with a better approach.
feed_controller.rb
def index
#hashtags = hashtag_refresh
end
def hashtag_refresh
Hashtag.order('created_at DESC').limit(10).uniq
respond_to do |format|
format.js
end
end
feed\hashtag_refresh.js.erb
$('.trends_li_container').html("<%= escape_javascript(render('feed/shared/hashtag_list')).html_safe %>");
routes.rb
get 'feed/hashtag_refresh', to: 'feed#hashtag_refresh'
hashtag_autorefresh.js
//Refresh Hashtags Partial
$(document).ready(function (){
setTimeout(refreshHashtag, 60000)
});
//Calls action refreshing the partial
function refreshHashtag() {
$.ajax({
url: 'feed/hashtag_refresh',
type: 'GET',
dataType: 'script'
})
}
feed/shared/ folder
_hashtag_list.html.erb
feed/ controller folder
hashtag_refresh.js.erb
Server Development Log
Started GET "/feed/hashtag_refresh?_=1462210930323" for 127.0.0.1 at 2016-05-02 13:45:05 -0400
Processing by FeedController#hashtag_refresh as JS
Parameters: {"_"=>"1462210930323"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 5]]
Rendered feed/shared/_hashtag_list.html.erb (0.0ms)
Rendered feed/hashtag_refresh.js.erb (11.5ms)
Completed 200 OK in 50ms (Views: 47.5ms | ActiveRecord: 0.0ms)
try changing your function refreshHashtag() to this
//Calls action refreshing the partial
function refreshHashtag() {
$.ajax({
url: 'feed/hashtag_refresh'
type: 'GET', //POST
dataType: 'script'
})
}
I think the problem is the returning value of hashtag_refresh. You expect it to return a collection of Hashtags, but actually it returns the return value of respond_to, which I don't know what it really is :P
Try modifying your controller like this:
def index
hashtag_refresh do |hashtags|
#hashtags = hashtags
end
end
def hashtag_refresh
yield Hashtag.order('created_at DESC').limit(10).uniq
respond_to do |format|
format.js
end
end
And your javascript
// Refresh Hashtags Partial
$(document).ready(function (){
setInterval(refreshHashtag, 60000)
});
// Calls action refreshing the partial
function refreshHashtag() {
$.ajax({
url: 'feed/hashtag_refresh.js',
dataType: 'javascript'
})
}
By the way, calling setTimeout recursively is preferred over setInterval because setInterval requires manual cancel, and if you forget to cancel, it will run forever. So your javascript can be like this:
//Refresh Hashtags Partial
$(document).ready(function (){
(function refreshHashtag() {
$.ajax({
url: 'feed/hashtag_refresh.js',
dataType: 'javascript'
}).then(function() {
setTimeout(refreshHashtag, 60000);
});
})();
});
Hope it will resolve your problem :)
UPDATE
If you got the error ActionController::UnknownFormat, then it simply means that rails don't recognize the format js or the mime type text/javascript. We can teach rails by adding some config in config/initializers/mime_types.rb
config/initializers/mime_types.rb
# The RFC standard mime type for javascript
Mime::Type.register "application/javascript", :js
# The legacy but widely used mime types for javascript
Mime::Type.register "text/javascript", :js
Mime::Type.register "application/x-javascript", :js

Reading variable value from Rails controller in view for Rails

I have an instance variable, #source_code in my Rails controller that I want to retrieve in my Ajax response via the success function. I am calling this Ajax function from my index.html.erb file and it renders a show.html.erb file. I want to get my text area to print out the #source_code.code value.
SourcesController.rb
def show
Rails.logger.debug("REACHED: show >>")
#source_code = Source.find_by(id: params[:id])
Rails.logger.debug("REACHED: source_code >>" + #source_code.code.to_s)
#sources = Source.all
end
index.html.erb
function updateTextArea(source_id){
console.log(source_id);
$.ajax({
type: "GET",
url: "/sources/" + source_id,
data: {source_id: source_id},
success: function (response){
alert("Ajax success")
console.log("<%= #source_code %>");
editor.session.setValue("<%= #source_code %>");
},
error: function(){
alert("Ajax error!")
}
});
Expanding on Nycen's answer, you first want your controller handle the ajax request and return a JSON response:
def show
respond_to do |format|
format.json { render json: Source.find_by(id: params[:id]) }
end
end
PS: Take care with that, it will send all of the fields of your Source record down the wire. I call slice (see ActiveRecord.slice()) on the model to limit the fields returned in the JSON.
Then your JavaSript needs to use the JSON result of that ajax call:
function updateTextArea(source_id){
console.log(source_id);
$.ajax({
type: "GET",
url: "/sources/" + source_id,
success: function (response){
alert("Ajax success")
console.log(response.code);
editor.session.setValue(response.code);
},
error: function(){
alert("Ajax error!")
}
});
It depends on how your routes are setup, but there should be no need to set the data property in the Ajax call. Your route is likely to pull it from the URL path: /sources/12345.
Note there is no show.html.erb with this setup. There is no view, your controller just returns JSON.
You're expecting your success handler to have access to #source_code just like a "show.html.erb" view would, but it doesn't work that way.
When you use ajax, the method is called from the browser; it's a piece of code you send away from your server, it can still interact with it, but it doesn't have access to the controller variables.
So, your show action needs to render something your handler can understand, for instance json. Then you'll have access to it in your success by reading your "response" variable.

Use Ajax or jQuery to Make Table Element in Rails App Load Separate From Page

I have a page with a list of user sites and on it I am making an API call to check the status of something for each site. The problem is that it makes the page take forever to load, so I would like the page to load and then that table element to update after it's done checking using AJAX or jQuery. I'm not great with AJAX or jQuery though and all the Rails/Ajax tutorials I've been reading seem to deal more with forms and data stored within the database. Here's my table element:
Part of My View
<td>
<% if HTTParty.get(site.domain + 'api')["status"] == "ok" %>
OK
<% else %>
Error
<% end %>
</td>
The Controller Action Loading View
def sites_page
#sites = Site.where(user_id: current_user.id)
render 'sites_page'
end
How can I make this load separately as mentioned above? I know I don't have any attempted code yet, but I really don't know where to start.
Thanks for your help.
Just attach AJAX call to the td on window load, it will be evaluated later after page is rendered. AJAX call can be something like this:
$(window).load(function() {
var target = $(".td-that-will-be-evauated-later")
url = target.data("url")
$.ajax({
url: url,
type: "GET",
dataType: "json",
success: function(result){
target.html(result.body)
},
error: function(xhr, status, error) {
$(target).html("error");
}
})
})
Url should point to the controller action that will fetch information for particular user, for example:
class UsersController < ActionController::Base
def fetch_info
#user = User.find(params[:id])
#response = #user.fetch_info
render json: {success: true, body: response.body}
end
end

Selecting data from another page in Ajax

This is my ajax handling code:
$.ajax({
url: "shirts/first?page=" + params[:page],
type: "GET"
})
How to tell Ajax to take the results from the next page in the shirts/first file?
I wrote the code as I've shown but it throws a error saying 'syntax error'! How can I solve this?
Also my .js.erb file if its of some help:
$("#container1").append("<%= escape_javascript(render 'shirts/first')%>");
If you're performing ajax pagination, you'll have to ensure you can handle the Ajax request on the controller (using respond_to), and send the correct data:
JS
#app/assets/javascripts/application.js
$("a.pages").on("click", function() {
$.ajax({
url: "shirts/first?page=" + $(this).attr("id"),
type: "GET"
});
});
You'd need to have your pagination buttons with the page's ID for this
Controller
#app/controllers/shirts_controller.rb
def first
#shirts = Shirt.where(your_query)
respond_to do |format|
format.html
format.js
end
end
View
#app/views/shirts/first.js.erb
$("#container1").append("<%= raw(escape_javascript(render 'shirts/first')) %>");
you have mixed the rails params and javascript code, in javascript
url: "shirts/first?page=" + params[:page]
has syntax error because of : charachter, and even if you remove it means you have a javascript object named params and page is a variable which refers to a key in the params object, whereas here params[:page] refers to a querystring which its key is page in the current request from the client.
So change it like:
$.ajax({
url: "shirts/first?page=<%= params[:page] %>",
type: "GET"
});
You have to be careful here, cause the code above means the current page is being loaded with the page in its querystrings like: http://example.com/homepage?page=helloworld and helloworld probably is the other page in your story.
and for your .js.erb file, in rails 3.0.8, you have to wrap every escape_javascript call with raw():
$("#container1").append("<%= raw(escape_javascript(render 'shirts/first')) %>");

Categories