Migrating ujs to co-exist with hotwire turbo_stream - ruby-on-rails

added ujs to rails 7.0.3 by pinning ./bin/importmap pin #rails/ujs#7
importmap.rb no shows
pin "#rails/ujs", to: "https://ga.jspm.io/npm:#rails/ujs#7.0.3/lib/assets/compiled/rails-ujs.js"
and application.js was amended with
import "#hotwired/turbo-rails"
import "controllers"
import Rails from '#rails/ujs'
the form, in rails 6 was stated for creation or update as:
<%= form_for(#cartitem, url: cartitems_path, method: :post, local: false) do |f| %>
<%= form_with(url: edit_q_cartitem_path(id: #cartitem_for_article.first.id), local: false, method: :patch) do |form| %>
adding data: {turbo: false} resulted in 2 unexpected behaviours. The rendered HTML does neutralise turbo, but the request is a local one:
<form data-turbo="false" class="new_cartitem" id="new_cartitem" action="/cartitems" accept-charset="UTF-8" method="post">
Instead of :
Started POST "/cartitems" for 127.0.0.1 at 2022-...
Processing by CartitemsController#create as JS
got
Started POST "/cartitems" for 127.0.0.1 at 2022-...
Processing by CartitemsController#create as HTML
Using pre-rails 6 syntax remote: true still renders as HTML notwithstanding the added tag attribute.
<form data-turbo="false" class="new_cartitem" id="new_cartitem" action="/cartitems" accept-charset="UTF-8" data-remote="true" method="post">
Also, this results in a fatal Can't verify CSRF token authenticity. error.
So there's something missing in this process to allow ujs and Hotwire to co-exist as per suggestion. What should be done?

Related

Rails 6.1 form_with doesn't send PUT request

I added the method: patch to the form_with helper (like it said to in this SO post)
<%= form_with(model: [:admin, contest], method: :patch) do |form| %>
...
and the <input type="hidden" name="_method" value="patch"> shows up (like it's supposed to) but then when I click "Submit", the request is still a POST request and I get the error
No route matches [POST] "/admin/contests/7"
I had the same issue, and resolved it by changing it to:
method: "patch"
Update: You're right, "patch" and :patch do the same. I also added the url from my routes file:
model#update
I think I need some more info. What does your controller look like? What model is it? Have you tried specifying the model and the url in form_with?

form_with performing action but not rendering page properly

I am working on a simple search functionality that is located in a user dashboard view (which also has its own dashboard controller). Now, the search function runs on a single model, and upon performing the action, it is supposed to go to the index page of that particular model. However, the index page does not get rendered after searching and it remains in the dashboard page even though the log says it redirects to the index page.
Here is the log:
Started GET "/detected_vehicles?utf8=%E2%9C%93&%3Aq%5Blocation_eq%5D=1&commit=Search" for 127.0.0.1 at 2019-05-02 10:33:08 +0800
Processing by DetectedVehiclesController#index as JS
Parameters: {"utf8"=>"✓", ":q"=>{"location_eq"=>"1"}, "commit"=>"Search"}
Rendering detected_vehicles/index.html.slim within layouts/application
Rendered shared/_flash.html.slim (3.1ms)
Rendered detected_vehicles/index.html.slim within layouts/application (80.9ms)
Rendered layouts/_navbar.html.slim (2.9ms)
Rendered layouts/_footer.html.slim (3.6ms)
Completed 200 OK in 326ms (Views: 271.7ms | ActiveRecord: 6.4ms)
Here is my form_with code:
= form_with url: detected_vehicles_path, method: :get, class: 'ui form' do |f|
.field
= select_tag(":q[location_eq]", options_from_collection_for_select(Camera.all, "id", "full_location"), class: 'form-control', id: 'detected_vehicle')
= f.submit 'Search', class: 'form-control'
I have tried doing the same thing using form_tag instead and it works as expected. Here is my code using form_tag:
= form_tag detected_vehicles_path, method: :get, class: 'ui form' do
.field
= select_tag(":q[location_eq]", options_from_collection_for_select(Camera.all, "id", "full_location"), class: 'form-control', id: 'detected_vehicle')
= submit_tag 'Search', class: 'form-control'
While I know that I can settle with the form_tag solution right now, I would like to find out what's wrong with how I constructed my form_with since it might become the standard soon for writing forms since form_tag and form_for are technically soft-deprecated as I have read.
If you look closely, when using form_with you are using JS for the request:
Processing by DetectedVehiclesController#index as JS
because form_with sets local: false by default:
:local - By default form submits are remote and unobtrusive XHRs. Disable remote submits with local: true.
So, add local: true to form_with and see what happens.

Rails 5.1.2 - form_with is not showing data-remote="true" in the html

Rails 5.1.2:
I'm trying to create an AJAX form using form_with in line with the Rails documentation and this GitHub thread.
This code:
<%= form_with url: '/' do |f| %>
<% end %>
and in fact this code:
<%= form_with url: '/', remote: true do |f| %>
<% end %>
both produce this html:
<form action="/" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="..." />
<input type="hidden" name="authenticity_token" value="..." />
</form>
Why isn't data-remote="true" appearing in the HTML, as the first link I have posted indicates it should, and how do I get it to appear?
I was having the same problem with a Rails 5.1.4 app. Using local: false fixed the problem.
<%= form_with url: '/', local: false do |f| %>
<% end %>
Default value for data-remote is configured by option Rails.application.config.action_view.form_with_generates_remote_forms. By default in Rails 5 this option is true. Search this through all your project, it seems that you migrated from Rails 4 or smth. else with overriding this option.
In Rails 5.1.2 By default, form_with assumes that your form will be using Ajax. You can opt out of this behavior by passing the :local option in form_with.
<%= form_with url: '/' do |f| %>
<% end %>
Above code produces
<form action="/" accept-charset="UTF-8" data-remote="true" method="post">
<input name="utf8" type="hidden" value="..." />
<input type="hidden" name="authenticity_token" value="..." />
</form>
Also If you want to use form without ajax, you can use below way -
<%= form_with url: '/', local: true do |f| %>
<% end %>
For me the addition these two lines to config/application.rb fixed it:
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.2
It will happen in Rails 5.1
With my config in new_framework_defaults_5_1.rb like this:
# Make `form_with` generate non-remote forms.
Rails.application.config.action_view.form_with_generates_remote_forms = false
And in my view file, I'm using like this:
= form_with(model: your_model , url: your_path, method: :post, local: false) do |f|
....your input here...
Now your html code will generate data-remote: true in your form.

Getting No route matches [POST] when using turbolinks

I have todo list app. In the application there are multiple places wher you can mark a todo done by clicking in a checkbox.
This is the erb
<% #todos.each do |todo|%>
<%= form_for todo, remote: true do |f| %>
<%= f.check_box :completed, :class => "dashboard_done_box", :id => todo.id %>
<% end %>
<% end %>
and here's the js
$(document).on('click', ".dashboard_done_box", function(){
$("#edit_todo_" + $(this).attr('id')).submit()
});
The routes.rb has the line
resources :todos
When I refresh the page it works, but when I am navigating to it I get this error.
Started POST "/todos/1" for 127.0.0.1 at 2014-05-07 13:18:45 +0200
ActionController::RoutingError (No route matches [POST] "/todos/1"):
It also works when I disable turbolinks.
This code works on other pages in my application it is just on one page I have this problem.
When it works in makes a PATCH request
Started PATCH "/todos/1" for 127.0.0.1 at 2014-05-07 13:44:08 +0200
Processing by TodosController#update as JS
Why does it do a POST request and how is it connected to turbolinks?
Update
Yosep Kim suggested I should make a post route
routes.rb
post 'todos/:id' => 'todos#update', :as => :todo_update
The form
<%= form_for #todo, remote: true, url: todo_update_path(#todo), method: :post do |f| %>
Now I get trough to the controller, but only with these parameters
{"controller"=>"todos", "action"=>"update", "id"=>"3"}
Conclusion: The form submission is not getting serialized. Why?
How does the form render?
Rails uses the PATCH verb to update because in rails applications a update is almost always a partial update. The PUT verb should be used for complete updates ( like when you overwrite a file ) Read more here Riding With Rails
Rails uses hidden fields to accommodate the html verb.
Your form should render like this
<form accept-charset="UTF-8" action="/todos/5" class="edit_todo" data-remote="true" id="roster_edit_done_todo_5" method="post">
<div style="display:none">
<input name="utf8" type="hidden" value="✓">
<input name="_method" type="hidden" value="patch">
</div>
<!-- What ever fields you need -->
</form>
Be aware if you have the form in a table. The table might make the form render strange.
There is a bug on latest 64bit Chrome dev/beta channel version 37,38.
If you use it, see https://code.google.com/p/chromium/issues/detail?id=388664
First of all, your code is creating two redundant requests, when the checkbox is clicked. The first one is fired by the form, and the second by the JS code you have. The one that is fired by the form would ONLY work one time after the page refreshes. Once you click on it, Turbolink would refresh the contents in the BODY without reloading the DOM, failing to attach the AJAX event handler to the form.
You can suppress the default behavior by using preventDefault. This should only fire the action once through the JS code.
$(document).on('click', ".dashboard_done_box", function(e){
e.preventDefault();
$("#edit_todo_" + $(this).attr('id')).submit()
});

Rails 3: Form_tag + remote: true not working even with proper JS?

I have a simple form for uploading a file:
<%= form_tag(admin_file_uploads_path, remote: true, multipart: true) do %>
<%= label_tag "Inventory Status" %>
<%= file_field_tag :inventory_status %>
<%= submit_tag "Upload" %>
<% end %>
And the source shows that jquery, jquery-ujs, and jquery-ui are all are included:
<script src="/assets/jquery.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery_ujs.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery-ui/js/jquery-ui-1.10.3.custom.min.js?body=1" type="text/javascript"></script>
I want to process form submission with AJAX. It seems like all the pieces are in place, but it's still being processed as HTML. The log says Processing by Admin::FileUploadsController#create as HTML. What am I missing??
You can't upload files via AJAX, so apparently your request comes as plain HTML, coz you don't have anything specific to :js and rails thinks it's just a plain HTML POST request.
You can't upload files via AJAX, but there are many gems that can helpful ,I'v used remotipart gem its really very nice and easy.
hope you will get your solution.
https://github.com/JangoSteve/remotipart

Resources