rails ajax update only once - ruby-on-rails

I have a remote_form_for that I use to let a user know if their form was submitted successfully. In this method I have :success=>'updateMain()
I would like to add an ajax update request to updateMain. The problem is that I can't find a way to make a single update request in rails (I know this is available in prototype).
The closest thing I've found is periodically_call_remote but this is not what I'm looking for as it continues to poll the server (and I only need it to happen once)
Another issue is that the ajax code needs to go into the updateMain js method, so I can't use periodically_call_remote as it automatically wraps the its js code with <script></script>.
I could write this manually with prototype but it would be nice to do it with rails. Any ideas?

In your controller method that your remote_form_for is submitting to, why don't you just use render :update?
def ajax_method
# If the form was valid
render :update do |page|
page.replace_html 'id_of_div_to_update', :partial => 'successful_form_submission'
end
end
The page will be updated each time you submit the ajax form.

Related

How to insert a form for a new record using Turbo/Stimuls?

The future of Rails seems to be moving away from UJS and towards Turbo and Stimulus. But, some features seem to require more code and more work vs old-school UJS.
For example: To insert a form inline that would allow the creation of a new record you could create a link like:
link_to 'add record', new_user_path, remote: true
then, in the controller:
def new
#user = User.new
respond_to do |format|
format.js
end
end
and, finally a new.js.erb view containing the content (form) to be executed in response to the new action.
One would think this would be simple to convert to Turbo simply by responding to:
def new
#user = User.new
respond_to do |format|
format.turbo_stream
end
end
and then change the new.js.erb to new.turbo_stream.erb with content like:
<turbo-stream action='append' target="<%= dom_id #user %>_new_form">
<template>
...the user form stuff...
</template>
</turbo-stream>
However, Turbo Streams do not handle GET requests. So, this approach does not work.
My question is: What is the Rails 7 way of handling this? I don't think UJS is the answer, since Turbo and Stimulus are "superseding" UJS functionality. Perhaps, the answer is to insert the new form using Stimulus, then use a stream to insert the subsequent new record following the POST request when the form is successful in the create action. But, this seems like so much more work than UJS is/was. It makes me think there's gotta be an easier, more fluid, less code way to handle this.
For this I would use turbo-frames :
First make an empty turbo-frame called new_record
Then you can have a link and set the data-turbo-frame="new_record"
this will act as if you clicked the link inside of the new_record turbo-frame
Then on the new template have a matching turbo-frame wrap your form and then
When you click on the new record button it will put the new record form in the spot I would say this is the hotwire way of doing it.

rails form post action without changing path

I've got a view that renders a contact form. This contact form is rendered through javascript. There is also a javascript filter that the user can set viewing options in. (Depending on the settings, different markers are shown on a google map. The user can then click on the markers and in the viewbox click on a view button that renders some info and the contact form below the map)
If I were to make a normal form and use the post method with a #contact and contact routes, I would have to rerender the entire page after the #contact#create method was called. Which would mean all of the current users filter options would be unset. I could obviously save the settings, but feel like this is a hassle.
What I would like is for the contact form to call a method upon submit without actually changing paths, but I have no idea if this is even possible. (i'm using simple form so an answer for that would be preferable)
Since your question is quite broad, I'll have to answer as such:
if this is even possible
Yes it's possible.
You'll have to use ajax to send an asynchronous request to your server.
Ajax (Asynchronous Javascript And Xml) sends requests out of scope of typical HTTP; you can send/receive "hidden" data without reloading (this is what you want):
Don't worry - ajax is really simple once you understand it.
There's a great Railscast about it here:
Implementation
For you, you will just have to get your form to submit over ajax (javascript). There are two ways to do this:
Standard JS (JQuery)
Rails UJS (unobtrusive Javascript)
Basically, javascript acts as a mini browser, opening a url on your server, handling the returned data & doing what you tell it on the path:
<% form_tag contact_path, remote: true %>
<%= text_field_tag "name %>
<%= email_field_tag "email" %>
<%= submit_tag %>
<% end %>
You'll then be able to back this up with the corresponding controller action on your server:
#app/controllers/contact_forms_controller.rb
class ContactFormsController < ApplicationController
def create
... #-> your own logic here
respond_to do |format|
format.js #-> when receiving a pure xml request, this will fire
format.html
end
end
end
#app/views/contact_forms/create.js.erb
$("body").append("<%=j #variable %>");
Without going into too much detail, this is the most efficient way to achieve what you want. I can elaborate if required.

rails 3.1: Is it ajax?

In rails 3.1, I implement as:
1. Define test action in post controller:
def test
#p = Post.first
respond_to do |format|
format.js
end
end
2. Define in routes.rb:
resources :posts do
collection do
get 'test'
end
end
3. In index.html.erb of post folder, I add link:
<%= link_to "test", test_post_path, :remote => true %>
4. Create test.js.erb file in post folder:
code jQuery
My question is: "Is my implement Ajax in rails 3.1?" I don't really understand about ajax in rails.
If no, can you give me a link about ajax in rails 3.1 and the technique I set up, what is it?
Yes it is ajax. When you add :remote => true to links and forms in rails, it automatically sends data to the server without refreshing your page on the browser. That's how ajax works in every language/script.
In your case, you can put js code in your test.js.erb file to update/interact the page (with jQuery). You might want to update some html div elements with the attributes of instance variable you set up #p .
Eg. in your test.js.erb
$("#some_div").html("<%= #p.title%>");
Then you have essentially made an ajax request to the server and update the client browser page with the server data without refreshing.
You request is do by Ajax from your link. But the return of your action can be not usefull to you.
You need add in your app/view/posts directory a test.js.erb file and fill it with Javascript behaviour you want.

Rails 3: Simple AJAXy Page updates?

I can't believe I've been looking four hours for this simple task, but I have.
In Rails 2.3, I could replace one section of a page with this simple code:
render :update do |page|
page.replace_html "div_id", :partial => "new_content",...
end
In Rails 3, Ryan Bates has me writing entire new javascript functions, switching from Prototype (rails default) to jQuery, and otherwise not enjoying life. The other tutes are no more straightforward.
What am I missing? How do we replace a <div> these days?
Thanks, guys. The official answer seems to be that, yes, the team felt simple is the enemy of good and made it more complicated.
The first key is to create a .js.erb file NAMED for the method CALLING the ajax update. So if the index method handles the update, put the raw javascript in index.js.erb. This goes in the views folder.
Second, the code that worked in index.js.erb was
m = $('list_users');
m.innerHTML = "<%= escape_javascript(render :partial => "reload_users") %>";
Then to make the call, add in the respond_to block of the controller method, add:
format.js
Finally, the calling view has:
<%= link_to "Update User List", #reload_users_path, :remote => true %>
By the way, supposedly all the old pages using page.replace will work if you install a plugin. The plugin download page suggests that it broke in the last releases of Rails 3 and has not been fixed. Also, various bloggers will come to your home and birch-switch you if you use it.
The whole RJS stuff makes the javascript inline and makes the dom very obtrusive. Also, by avoiding inline javascript you could open up other possible ways of optimizing you javascript by compressing and caching those files in browser. Thats the reason why RJS is getting out of scope from rails 3. A little bit of getting around with jQuery or Prototype for a day should get you on gears with these kind of small stuff and will help the project on long run.
Do you still have jQuery in there? I'd recommend it over Prototype any day...
If it's still there you can just use the following in your Javascript:
$.get("<%= url_for path/to/partial %>",
function(response) {
$("#div_id").html(response);
});
This gets the partial via AJAX and just dumps it into the div with id div_id.
Hope this helps!
I'm not even sure you need to make an AJAX call to load that partial. I believe that in a js.erb file, a call to render(:partial => object_or_path) will just return a string with all the html, which you can wrap in a jQuery object and append. Example:
$('#div_id').html($('<%= render :partial => #object %>'))
As far as I know, along the same line as the answer above, you can do something like this in your template:
<%= link_to "Update User List", #reload_users_path, :remote => true %>
And in controller, do this:
respond_to do |format|
format.js {
render :text => "alert('reloaded')"
}
end
This way you can have controller "execute" client side JS much the same as as render :update used to do. This is equivalent to doing the following in Rails 2:
render :update do |page|
page << "alert('reloaded')"
end
Is there any reason why this approach is not advisable?
Try this:
page.call "$('#div_id').html", render(:partial => 'new_content')

Posting a form through popup in Rails

I have a model called Details, and two controller methods new and create. New method displays a form to create Details (in new.html.erb), which gets posted to the Create method that saves it. (when it succesffully saves, it it renders the new.html.erb file with the details.) This works as expected.
Now i want a separate page with a link to fill in these details. I want the click to do the intended work through a popup, example redbox. When you click on that link, a popup should show the form, whose submit should post the form, and if it is successfully done, then refresh the original page. If the post is unsaved, then the same form should show the errors. What do i need to do to make it work in Ror? I guess i need some stuff to go in new.js.rjs and maybe create.js.rjs, but i can't really figure out what to put in those files.
Redbox updates the page's dom to add a div at the end of it. So your form is a part of the main page.
So if you add a form tag in this redbox, all your page will be reloaded as there's only one.
So you add anywhere in your page (preferably at the end) :
<div id="redbox" style="display: none;">
<%= form_for #details do %>
# Whatever form fields you want here
<% end -%>
</div>
You do a link that'll open the redbox :
<%= link_to_redbox 'Open The Details Form', 'redbox' %>
This will display your redbox with your form.
And as it is the same page, not a new windows, when you'll validate your form, it'll reload the all of it.
I used a link_to_remote_redbox for this, which on clicking, fetches the form rendered by the new method call in a popup widnow. it submits to the create function and it is now working. actually i had previously made it work without ajax and i was having difficulty in making it work with ajax. the problem was solved once i made separate partials for ajax calls, and doing:
respond_to do |format|
format.js { render :template => 'detail/ajax_template'}
...
end
I provided different templates for both create and new method calls, used the :html => {:id => 'some-id'} in form and the :update => {:some-id} to replace the form with the message that it worked correctly.
So I didnt know that i needed separate templates for the different styles of forms, and that i needed to use the :update option to replace the form when i asked the above question.

Resources