Can you piggyback a data response to an Ajax partial rendering - ruby-on-rails

I'm using ajax to update a partial, but i would like to get some data back from the server at the same time.
$('<%=escape_javascript #my_params.to_json%>');
$("#partial").html('<%= escape_javascript(render partial: "view/partial" )%>');
gives me the response with both data and partial rendering in it, but it breaks the Ajax render, so the partial is not rendered.
Using Rails 4, ROR. no errors in the browser or Rails
if i refresh the page i get the result i wanted.
I know this must be easier than i'm making it.

Assuming that you are using js.erb format for rendering ajax page.
Inside the view partial, write the code
run your js code here or assign to global js variable

I'll leave this here for edification, but my friends told me that they would disavow me if i abused a cookie this way. So i switched my implementation, can't afford to lose any friends. They told me to focus on making the turn around time for the ajax call fast. I still needed to know when the object had completed rendering so i simply added a hidden element in the partial and i set its size to zero and wait until the partial rendering changes the height from zero. It was pretty funny to see the interactions with two tabs open to the web page, even though i was planning to use the session ID avoid crosstalk.
Okay, I decided that for my purposes the best way was to put the data in a cookie and just detect when the cookie changed. This allowed me to change the cookie at the end of the send_data command and both get the data for the image position relative to the other image as well as detect when the send_data completed so i could slide the image into place (over the animated wait image).
it looks like this on the server
send_data(image.to_blob { self.format = 'png' },
type: 'image/png',
disposition: 'inline')
cookies[:duck_data] = { :value => $cookie_data.to_json}
and this on the client side
wait_for_paint=->
if $.cookie('duck_data') == 'keep waiting'
setTimeout (->wait_for_paint()), 250
else
my_data= $.parseJSON($.cookie('duck_data'))
do_ajax_response(my_data)

Related

Rails 5 after submitting form / action stay on exactly the same spot on page

I have this webshop, and on one page you see
products;
with a submitting form for a booking;
your order with its bookings;
with a removing link for a booking;
and an updating form for a booking.
Both the order.bookings and the products make potentially long lists on a html page.
The whole booking works by only a booking_controller.
What the booking_controller does:
Takings in the (new) params of a single booking or the destroy action.
Saves the new order.
Redirects to the store.
Works fine, just using ruby and html.erb.
Only problem, and this really needs to change, is that obviously after each redirect the browser goes to the top of the page. The browser isn't focussed. Or better to say, the browser should remain, but doesn't.
I get that your doing all these things on the server-side, so a page reload, or better to say, data-refresh, is necessary. What I don't want is building this whole thing again on the client-side (JS).
Can't I simply say something like: after data refresh redirect to exact same spot on page. Ignoring all the difficulties an asynchronous request would give, or am I exaggerating and is a little JS easy?
With Rails, using ajax is very easy however if you're not familiar with ajax at all it can be a bit daunting at first. Luckily there are many tutorials on the subject. Basically, add the remote: true option to your form_for statement and rails will automatically understand you want it to make a 'POST' request in JS format. It's important to realize that the incoming HTTP request is in JS format because you'll then need to specify handling that event in the controller. Such as:
def create
#Do whatever saving and processing you need here
respond_to do |format|
format.html { redirect_to some_path_here }
format.js { } #By not adding anything in the brackets here, you're telling rails to fetch a js view file that follows standard rails convention and so it should be named 'create.js.erb'
end
Then in your controller's views folder create the view file create.js.erb. In that file you'll want to refresh whatever part of the page needs updating which usually involves hiding the old div that was there and appending a partial in its place. I usually leave an empty div with an ID on the page (in this case your new_whatever_page.html.erb that I then call in the js.erb file to append a partial to:
In your create.js.erb add:
$("#the-id-of-the-div-in-your-new-view-page").html("<%= escape_javascript(render 'order_table') %> #This basically says, find the div on the current page with a matching id and then append the partial named _order_table.html.erb to it.
Now just make a partial named
_order_table.html.erb
in the same views folder and put whatever content you want to insert or update.

Displaying flash message in portion of page that is otherwise not updated

I'm looking to display my flash messages in a portion of the page that is otherwise not always in a partial that gets updated.
In other words, I may submit a form that updates a partial via ajax. But I want to display the flash message in a portion of the page that is outside of that partial.
I could have some javascript in every single necessary js.erb file to update the flash partial, but that seems crazy. Is there a more simple way of going about this?
I don't have to necessarily use flash messages either if something custom would work better.
Thanks!
You can do it the low-tech way by using a :remote call on your form that, when executed, will inject some HTML back into your page from a partial of your choosing.
It's pretty easy to do in a .rjs view:
page['flash'].html(render(:partial => 'flash'))
You can also do it in a .js.erb view using jQuery:
$('#flash').html("<%= escape_javascript(render(:partial => 'flash')) %>");
I tend to think the .js.erb method is a lot more ugly, but we all have our preferences.

Rails 3 render partial without reloading images

I have a view 'edit.html.erb' which renders a partial.
<div id="exerciseslist"><%= render 'exerciseslist' %></div>
Inside 'edit.js.erb', I have the following line which reloads the partial each time something is updated.
$('#exerciseslist').html('<%= escape_javascript(render("exerciseslist")) %>');
The partial is a table with a bunch of items including images for each one and some buttons. All that is changing in the partial is the button. If a submit is successful, the button toggles state indicating that it has been added.
It's working fine, the problem is I don't like the way the images flash as the request happens, the items are also inside a scrollable section which looses it's state each time.
Is there a good way to just load the state of the buttons without rendering the full partial? Or is there a simple way to stop the client requesting the images each time?
I have done some reading and found pjax and backbone.js, are either of them a good way or is there a simpler rails way to do this?
Thanks,
Mike
Without seeing code, it's hard to be sure, but I think it could be done with just Rails. Instead of re-rendering the exerciseslist partial on submission, you could write an AJAX request to handle submission of the new data and on success, have the callback change the button state, rather than reload the partial.

Rails take base64

In rails i need to take a base64 string, and use it to generate a picture in rails. Now i'm having trouble, because i need to interact with AJAX calls (im strictly working on the server side, another guy is doing that client work) to send pictures. So far i've been taking requests in my application by having data transferred through the url (in the AJAX requests) but now im not sure if it's possible to transfer such a huge string through the url. How could i take in the data (like how could he pass it to me) to generate a picture.
Note: i've been using paperclip for my application so far, but now uploading through the form is not an option, it needs to be in an AJAX call where data is passed in a single call.
You're right, most browsers limit the length of a URL. The limit on IE8/9 is 2083 characters. Even if your particular browser has a higher limit, many servers limit the URL length as well (apache's default limit is right around 8k). It would be best to submit the image as a POST request with the data in the POST body.
I would use jQuery to POST JSON data to the server. In the controller, if this is set up correctly, you won't have to do a thing to parse the JSON. ActiveSupport will recognize the content type and parse it out into the params hash automatically.
Actually posting the data will depend on which javascript library you're using. Here's an example in jQuery, which you'd probably want to wire up to the onclick event of a submit button. This assumes you have a named route called process_image. This code would go in your view.
$.post(<%= process_image_path %>, { b64_img: "your_base64_image_data" });
In your controller, you can access the posted data with params[:b64_img]. If you want to return something from the controller back to the client, you can do this in the controller:
render :json => #model_object
And change the jquery call to look like this so you can do something with the return value:
$.post(<%= process_image_path %>, { b64_img: "your_base64_image_data" },
function(data) {
// do something with the data returned by the controller
});
Hope this helps. You can read more about the jQuery post call I used here: http://api.jquery.com/jQuery.post/
Dan

rails 3: (probably ajax question) need embeddable a banner on a html page that pulls a different 'joke' from our app every N seconds

I've never done ajax stuff myself, and this seems like an ideal feature to add to my app to learn how to do it...
My app maintains a database of jokes.
I'd like to provide a simple way for anyone to add a small banner to the html on their webpage that will display a new joke every N seconds.
It seems the two approaches are:
1) iframe where the url/view hit by the iframe has a meta refresh tag and randomly pulls a joke each time the url is hit. But iframes can resize to fit content, and I'm not sure if browsers will refresh the contents of the iframe.
2) the right way ... ajax. But I have no idea if this is a "big" or "trivial" job for a rails 3 app, and no idea where to get started.
Any pointers on doing this would be deeply appreciated!
I'll use jQuery for this example but the overall technique should work pretty much the same with any other AJAX framework.
In your JavaScript, you'll want to use $.ajax to grab a new quote from your server and setTimeout to get periodic updates; something like this:
var n_seconds = 5; // Or whatever you want.
var timer = null;
function replace_quote() {
// Do a $.ajax call to your server.
$.ajax({
url: '/some/route',
type: 'get',
dateType: 'htm;',
success: function(data) {
// Replace the quote with the new one.
$('#quote-container').html(data);
// And restart the timer.
timer = setTimeout(replace_quote, 1000 * n_seconds);
}
});
}
replace_quote();
If you start out with an empty quote box then you can simply call replace_quote() to give it an initial value through your AJAX call.
You could also use setInterval to call your quote replacer. Then you wouldn't need to manually restart the timer with the setTimeout call but you would run the risk our updates fighting each other if an AJAX call takes longer than n_seconds.
If you still want to provide a link for updating the quote then bind the link to a JavaScript function something like this:
function manually_replace() {
clearTimeout(timer);
replace_quote();
}
Calling clearTimeout will, effectively, reset the timer when they change the quote themselves.
Then, in your Rails app, you'd add a route for /some/route and the controller would simply grab a random quote from your database and then use render :partial => 'quote' to send back just the HTML snippet for the quote without all the usual layout wrapping.
Handling AJAX requests in Rails (or any other framework) is pretty much the same as handling any other request, the only difference is that you won't send back a full page, you just send back a little piece of HTML or a blob of JSON (or XML) for the client to process and render. Hence the size difference between the client-side and server-side outlines above.

Resources