Rails + ajax, my "edit.js.erb" is not being run - ruby-on-rails

I'm trying to setup ajax within rails, but I am having trouble getting my "edit.js.erb" to be ran
My edit.html.haml
= f.check_box :foo, {checked: eligibility_data.foo, class: "foo", remote: true}
controller
def edit
#survey = Foo.find_by_id(params[:id])
respond_to do |format|
format.html
format.js
end
end
edit.js.erb
alert("Testing");
How can I get edit.js.erb to run? Once it's working I want to append html to my view, will I be able to place that html right into my js.erb, or will I have to make a partial of some sort?

You can't append remote: true to a checkbox and expect it to fire off.
It needs to either be attached to the parent form tag of said checkbox, or you need to write some js that watches that checkbox.
If you go the watcher route, the JS will send an ajax call when the box gets clicked on.
Here is a link on how to do AJAX with jQuery (which is built into rails)

Related

Rails form submission not happening in the background

I have a Rails 5.2 app, where I'm using form_with, which is generating this HTML:
<form id="post-0" class="" action="/posts.js" accept-charset="UTF-8" data-remote="true" method="post">
The form is submitting successfully to the PostController's create action.
def create
#post = current_user.account.posts.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to posts_path, notice: 'Post added.' }
format.js { render :create, status: :created }
else
format.html { render :index }
format.js { render :create, status: :unprocessable_entity }
end
end
end
It is then rendering the JS view:
app/views/posts/create.js.erb
alert('created');
However, in my browser, I'm literally redirected to http://localhost:3000/posts.js where it shows the javascript code. Meaning, the form submit doesn't seem to be happening in the background.
I would have expected to still have stayed on the page the form was on, with a Javascript Alert appearing saying "created".
Is there's something silly I've missed? Seems to me it must be something with form_with that I'm not doing right.
I tried swapping it for form_for #post, remote: true, format: :js do ... but that had the same problem.
At this point, I can't tell if the problem is in View that shows the form, or in the Controller's create action. The controller is rendering create.js.erb and the URL shown is http://localhost:3000/posts.js which does seem to suggest it's a Form problem in the View.
This app is Rails 5.2. I'm not sure it's relevant, but I've removed the Asset Pipeline for Webpacker, I do have rails-ujs installed (as it is showing the confirm dialog in these link_to links as expected <%= link_to('Destroy', user, method: :delete, data: { confirm: 'Are you sure?' }) %>
Form submissions can occur locally (ie. not remote) due to a number of reasons.
Some common reasons local submission may be occurring when using form_with include:
local: true
The local attribute is optional for form_with. If not provided, form_with will by default set local: false.
true will set the form to be submitted locally (standard form submission), not remote/asynchronously.
false will set the form to be submitted remotely/asynchronously.
Any value other than false (including :false which is a symbol not a boolean) will be interpreted as the value being true (ie. submit locally).
Javascript triggered form submissions
Despite the setting of the local attribute being set to something that should trigger a remote/asynchronous form submission, the form may still be submitting locally if you're triggering the form submit event via Javascript.
In the example given in question, the HTML generated by the form_with use is as expected, so attributes provided to form_with are not the problem in this instance.
If javascript is being used to submit the form, that could be the problem. For example, even with data-remote="true" on the form, this javascript will be a problem:
document.getElementById('form-0').submit();
This submits the form, but doesn't raise a submit event for rails-ujs to intercept via an onsubmit event handler.
Working with the Rails Unobtrusive Javascript Adapter
To have the form submission triggered by javascript (whether you're using jQuery, Stimulus JS, or anything else) you need to use a mechanism that rails-ujs (or jquery-ujs) will intercept for you.
Rails provides the Rails.fire custom javascript event wrapper in rails-ujs, which can by used like this:
Rails.fire(document.getElementById('form-0'), 'submit');
You're doing a very basic mistake. By using ajax you can't use format.js. This Ruby Module is used to redirect the page. instead you should be using render json: { status: 200}
saw your job on Upwork. No need to spend $100 on this!
<%= form_with url: content_export_path, method: :post, id: 'ce_form1', data: { remote: true } %>
Look where the remote: true declaration is... (inside data hash)
Let me know if this works.

When does rails controller knows when to use serve embedded html or js

If I'm calling the index action in UsersController, when does the Rails controller know when to serve up index.html.erb or index.js.erb? It seems that setting links with the property remote: true will direct me index.js.erb instead of index.html.erb ?
link_to 'user#index', remote: true (=> index.js.erb)
link_to 'user#index' (=> index.html.erb)
Are there more scenarios?
How does rails know the difference between a regular get request or a javascript get request?
Can someone just clarify rails controller defaults when it comes serving up embedded javascript/html file? Thanks!
This thing are done by rails controller. For example, if you have index controller and you want to respond it with html and js
def index
respond_to do |format|
format.html ## respond to embedded html
format.js ## respond to js but it is called if remote data is passed (i.e if remote: true is set)
end
end
If you have pass remote in your index page (index.html.erb)
<%= link_to "Show", show_path, remote: true %>
Then it will respond to index js (i.e. format.js). You need to create index.js.erb file to define logic for it.
You can see in this guide too.

Respond with javascript to an HTML request?

Is it possible to respond to an HTML request with javascript? By this I mean that I don't want the page to be refreshed and plus execute some javascript code. I wonder if this is possible by changing only the server side?
In my action, I have something selected to respond to js and html like this:
respond_to do |format|
format.js
format.html
end
And I have a .js.erb file that, of course, should be rendered when the browser requests a javascript.
Can this be done? How?
You cannot do this by only changing the server side code. If you'd like javascript to be executed upon the server's response, then the form will need to be submitted through javascript. This is because javascript will eval the response from the server and run the code.
This can somewhat be trivially added in Rails:
<%= form_for #user, remote: true %>
When it is submitted, then you can send back javascript. For example, to alert that a user was added:
/app/views/users/create.js.erb
alert("user <%= j #user.email %> was added");

Rails - How do I get my remote form to respond with JS?

I have a page that list items. Below each item it lists out any comments for that item
(comments is a nested resource under items).
You can add a new comment in-line on the items page. When you do that, it was reloading the whole page so I want to change it to use Ajax and just use jQuery to insert the comment.
So I changed my comments/_form.html.erb to use :remote=>true
<%= form_for([#item,#comment], :remote=>true) do |f| %>
I added a format.js in my comments_controller:
def create
#comment = Comment.new(params[:comment])
#comment.save
respond_to do |format|
format.js
format.html { redirect_to items_path}
end
end
And created a simple comments/create.js.erb to insert the new comment onto the page:
$("#comments").append("<%= j(render(#comment)) %>");
However, when I submit a comment (even with the :remote=>true on the form) it keeps reloading the whole page/ignoring my .js file.
So I deleted format.html from the respond_to (since I don't want to use that option), but then it gives me the error Completed 406 Not Acceptable in 4ms (ActiveRecord: 0.2ms)
How can I get it to stay on the current page and respond with my create.js?
I just found the problem:
I was submitting my comments form with javascript: this.form.submit(). That worked fine when I wasn't using :remote=>true. However for some reason breaks when I make the form :remote=>true.
If I use an actual submit button, the code in my question works fine.
OR if I change my JavaScript from this.form.submit() to using jQuery to select the form by id and submit that, that works too:
$("#new_comment_<%= #item.id %>").submit();
I came across this question when trying to figure out something similar in 2020, using Rails 6.
I have a form created with form_with, which is remote: true by default, and I was submitting it in a Stimulus.js controller using the submit() function on the HTMLFormElement. This didn't work, but using a <input type="submit"> button instead worked, just like in the original question.
The reason behind this is that calling submit() in JavaScript doesn't trigger the onsubmit event on the form, while clicking a <input type="submit"> button does trigger this event (MDN docs). Rails' handling of remote: true depends on this event being fired, so the behaviour breaks.
I used the workaround from this answer to submit my form in JavaScript, and the remote: true behaviour now works as expected.
Also, if you're using rails-ujs, you can use this wrapper to submit the form (source):
form = document.querySelector('form');
Rails.fire(form, 'submit');
I hope this helps someone else!
You should add :format => :js onto your form_for
And possibly update,
format.js { render :nothing => true }

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.

Resources