ActionController::UnknownFormat in Rails 5 - ruby-on-rails

I have some product list where the user can add/remove items from their product list. I would like the mentioned iteration to be done via ajax with format.js
This is part of my input view where do i have the buttons to add/remove user items from product list:
.input-number__add
= button_to '', product_add_path(id: product_item), remote: true, class: ''
.input-number__sub
= button_to '', product_reduce_path(id: product_item), remote: true, class: ''
Here is my method where I add quantity in my item list in ProductItemsController:
def add_quantity
#product_item.quantity += 1 # increase 1 to the quantity
if #product_item.save
respond_to do |format|
format.js { render partial: 'product_items/add_quantity' }
end
end
end
What it does is go to 'product_items/add_quantity.js.erb' update the data and answer the request via js, but when it is reading the respond_to format.js I get the error:
ActionController::UnknownFormat, highlighting this line: respond_to do |format|
I saw in previous questions that give this solution respond_to :html, :json
but this doesn't work for me.
How could I solve this problem?
Thank you for reading me.

Are you sure the route helpers product_add_path and product_reduce_path point to the add_quantity endpoint?
You can also try forcing the format:
product_add_path(id: product_item, format: :js)
NOTE Don't forget you need the rails/ujs library in order to use remote: true functionality

Related

dynamic content in ajax while rendering partial views

How do I get dynamic content when user clicks on different links?
views/dashboard/index.html.haml
.container
- #trips.each do |trip|
= link_to trip.id, quick_view_trips_path, remote: true
I'm pretty sure the quick_view_trips_path is incorrect as all the links are this:
1
13
51
Somehow I need to make these links dynamic, and then when user clicks on it, the modal window would be dynamic too.
If I replace quick_view_trips_path with just trip
= link_to trip.id, trip, remote: true
Nothing happens, and the url changes to the correct url, but my modal window doesn't get rendered through ajax. Here's an example of what the url looks like now:
1
In addition to what I'm trying to accomplish with dynamic content, is there a way to maybe change my url like so:
1
Is it possible to get ?quick_view=on appending to end of URL and make everything work again?
Here are the rest of my code:
views/trips/quick_view.js.erb
$('body').append('<%= j render partial: "trips/quick_view" %>');
views/trips/_quick_view.html.haml
.root-container
= #trip.title
= #trip.image
= #trip.more_details
This doesn't work either right now, as my application returns undefined method
routes.rb
resources :trips do
collection do
get 'quick_view'
end
end
trips_controller.rb
def quick_view
respond_to do |format|
format.html # quick_view.html.erb
format.js # quick_view.js.erb
format.json { render json: #trip }
end
end
Do I need to add anything to this controller as well to ensure the correct content will be generated through the partial?
How about this way,
Path
link_to trip.id, quick_view_trips_path(:js, trip_id: trip.id), remote: true
This will render, 1
Controller
def quick_view
#trip = Trip.find(params[:trip_id])
respond_to do |format|
format.html # quick_view.html.erb
format.js # quick_view.js.erb
format.json { render json: #trip }
end
end
It will respond views/trips/quick_view.js.erb file

Rails form_tag remote example

I have this incredible simple form:
<%= form_tag("/portal/search", method: 'get', remote: true ) do %>
<%= label_tag(:query, 'Search for:') %>
<%= text_field_tag(:query) %>
<%= submit_tag("Find") %>
<% end %>
<div id="results"></div>
I know from the documentation, I can use AJAX through the remote option:
<%= form_tag("/portal/search", method: 'get', remote: true ) do %>
Then I get stuck. I know how to generate results in a view/partial, but how do I get that partial inside the div element? I know a bit of JQuery, so I can select the element. I found a lot of results, but they seem to miss that lightbulb moment for me. I am using Rails 4.1.6
My results are just simple records from a model, like Book (title, author)
Thank you for helping!
EDIT
I've won the cup for missing the point by a long shot. I had to add the search.js.erb inside the view folder instead of assets.
Let's say you get #results out of your search method.
In the controller, search method:
respond_to do |format|
format.html {render or redirect_to wherever you need it}
format.js
end
Then all you need is a file named search.js.erb to run the required js at the end of your request. It might look something like:
$('#results_div').html("<%= j #results.pluck(:title).join('<br/>') %>")
When you add remote: true jquery-ujs will provide you the ajax request (by default this javascript lib is required in app/assets/javascripts/application.js).
The ajax call will request a 'text/javascript' response. for that reason your server code should reply with:
# action
def search_query
respond_to do |format|
format.js {
# additional code
}
end
end
If in your view (search_query.js.erb) you provide javascript, it will be executed. That is why everyone is replying you with a $('#my_div_id').html('my html text') suggestion, which when executed will replace your div content with the new HTML.
If for some reason you want to return a json data structure, then you should provide a different data-type:
form_tag("/jquery_ujs/search_query", remote: true, 'data-type' => :json) do
# ....
end
And you should reply with:
# action
def search_query
respond_to do |format|
format.json { render json: #my_object }
end
end
And handle the success event:
<script>
$(document).ready(function(){
$("form#my_form").on('ajax:success', function(event, data, status, xhr) {
console.log("Great!");
// use data to access to your json data structure
});
$("form#my_form").on('ajax:error', function(event, xhr, status, error) {
console.log("sorry mate!");
});
// ....
})
</script>
You can also request a html response (in case you want to return a table, for instance), with :'data-type' => :html and format.html { render layout: false }
Ajax
Firstly, the Rails UJS (unobtrusive javascript) driver just gives you a "canned" way to send an ajax request to your browser. To avoid confusion, it's best to appreciate that you will be sending Ajax requests regardless of whether you use Rails UJS or the standard Ajax method
This means that the process of capturing the response from your Ajax is still the same - you need to make sure you have to catch the response from the system
Either :-
#app/assets/javascripts/application.js
$(document).on("ajax:success", ".element", function(status, data, xhr) {
// do something here
});
or
#app/controllers/portal_controller.rb
class PortalController < ApplicationController
def search
respond_to do |format|
format.js #-> app/views/portal/search.js.erb
format.html
end
end
end
#app/views/portal/search.js.erb
//something here
Fix
how do I get that partial inside the div element
You'll be able to use JS:
#app/controllers/portal_controller.rb
class PortalController < ApplicationController
def search
#results = ...
respond_to do |format|
format.js
format.html
end
end
end
#app/views/portal/search.js.erb
$(".div").html("<%=j render #results %>");

Rails AJAX - don't redirect or render

Using rails and .js.erb to make an AJAX request (and append values to a div), how do you prevent rendering a new layout? In other words, stay on the same page without going anywhere and just append the fresh data from the server in a div. No reloading the same page, no redirecting.
At the moment my controller looks like this
def update_shipping
#order = Order.find(params[:id])
#order.shipping_option_id = params[:shipping_options]
#order.save!
respond_to do |format|
format.js
format.html
end
end
and my form like zisss:
<%= form_tag update_shipping_order_path(#order), method: :put, remote: true do %>
<%= select_tag 'shipping_options', #options_for_select, onchange: 'this.form.submit()' %>
<% end %>
and my routes look like a so:
resources :orders do
member do
put :update_shipping
end
end
But I get a 'Template is Missing' error
Please help!!
You need to add a update_shipping.js.erb file under app/views/your_controller/ directory. Note the name of the javascript file should be same as the action. Since you have a remote:true in your form so rails will try to render a javascript template in your case update_shipping.js.erb.
Now in your update_shipping.js.erb file write some basic javascript to update the page elements like
#update_shipping.js.erb
$('.some-div').html(<%=j #model.some_value' %>)
Try this:-
respond_to do |format|
format.js { render :nothing => true }
format.html
end
If you don't want to render a layout, you can use !request.xhr? like so:
respond_to do |format|
format.html { layout: !request.xhr? }
format.js
end
If you're looking to get your ajax-powered JS to fire, you just need to call your .js.erb file the same as your view:
#app/views/controller/update_shipping.js.erb
alert("This JS is returned & fired after the Ajax request");
You'll be best doing this in your routes.rb too:
resources :orders do
put :update_shipping
end
A little late, I came across this searching for the same issue. It must of slipped out of my mind at some point while working with action cable, but what is needed is a http response code of no_content. Http response codes tell the browser how to act when a request is returned. Here is a link to a list of them, and their symbols in rails. More on 204 no content
Here is how it would look:
def update_shipping
#order = Order.find(params[:id])
#order.shipping_option_id = params[:shipping_options]
#order.save!
head :no_content #or head 204
end
edit: what solved the solution for me was a link provided by William Denniss in this stack overflow question

Rails: best_in_place collection issue

My app runs on two different database, and I use the application logic to work on them.
I have the User model on an external db and I only records the id on my default_role class.
So in the index template I fetch the accounts from remote, and for each of them I have to query my table to print some immutable information and I want to give the possibility to change role in my table
Index information = remote tables information (name surname ecc) + my table information (role)
Using best_in_place to edit the role_id field of my users.
The problem is my index cycle #operators which comes from outside buy I need to change role which is on my side!
- #operators.each do |ope| #cycle users
%tr
%td
- user = User.find_by_bay_id(ope.account_id)
- df = DefaultRole.find_by_operator_id(user.id)
= best_in_place [:admin, df], :role_id, :type => :select, :collection => [[1, 'admin'], [2, 'coordinator'], [3, 'operator'], [4, 'base']]
and my update in controller:
respond_to :html, :json
def index
#operators = some logic from model where I get all the users
end
def update
#df = DefaultRole.find(params[:id])
#df.update_attributes(params[:default_role])
respond_with [:admin, #df]
end
But it didn't even call my update method in the controller.
It normally checks the collection tag, allows me to change it but it doesn't allow me to submit.
What am I doing wrong?
EDIT
My browser doesn't catch any request.
Best_in_place gem uses JSON calls to update the content . In this case you should have respond_to json statement in your controller , something like this :
def update
#df = DefaultRole.find(params[:id])
respond_to do |format|
if #df.update_attributes(params[:default_role])
format.html { redirect_to root_path, notice: 'Role was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #df.errors, status: :unprocessable_entity }
end
end
I find it strange to include variable specifications in your view , they belong to the controller (- user = User.find_by_bay_id(ope.account_id)
- df = DefaultRole.find_by_operator_id(user.id) .
I finally found the error.
https://github.com/bernat/best_in_place/issues/217
It was a Jquery issue on that version of best_in_place. Running:
bundle update
and restarting the server solve the problem, thanks everyone

update different divs using ajax in rails 3.2

I recently started with Rails 3.2 and am stuck while trying to implement some ajax functionality in my app. I followed this railscast completely (http://railscasts.com/episodes/240-search-sort-paginate-with-ajax). Beyond this I want to implement a shortlist button for each product which lets user shortlist products and store them in the session. I also want a small list of shortlisted products to show up on the same page, which needs to be ajax updated.
I am wondering what is the best way to do that. I currently implemented the link_to buttons with remote tag and a helper function to change the link to shortlist/unshortlist. I also, used a conditional div to show the shortlist based on the length of shortlist. However, the issue is that whenever I shortlist, the order of the products table is also reset.
Here are snippets of my code :-
Application_helper.rb
def shortlist_unshortlist_link(product_id )
if (user_session.already_shortlisted? product_id )
link_to 'Unshortlist', { action: 'unshortlist', id: product_id }, remote => 'true'
else
link_to 'Shortlist', { action: 'shortlist', id: product_id }, remote => 'true'
end
end
def shortlist_div
shortlist=user_session.shortlist
if (user_session.shortlist.length > 0)
render :partial => 'pages/shortlist_fields'
end
end
products/index.html.erb
<div id="product">
<% #products.each do |product| %>
<tr>....
<td><%= shortlist_unshortlist_link(product.id.to_s) %></td>
</table>
</div>
<div class="shortlist"><%= shortlist_div() %> </div>
products_controller.rb
def shortlist
user_session.add_to_shortlist(params[:id])
redirect_to products_path
end
def unshortlist
user_session.remove_from_shortlist(params[:id])
redirect_to products_path
end
I think, the issue is because of redirect_to, but I am not getting how to avoid this without hurting the functionality. Am I on a totally wrong path here. Is this a good way to implement this. Any suggestions.
thanks,
Amit
you should use in shortlist method,
respond_to do |format|
format.html {redirect_to products_path }#shortlist.html.erb
format.js #shortlist.js.erb
end
and write your java script to #shortlist.js.erb file.
Do the same with unshortlist.
I agree with Sush, you didn't response to the ajax request from link_to.
In your controller, shortlist method, response to the ajax request
respond_to do |format|
format.html {redirect_to products_path }
format.js
end
By convention in Rails, format.js will execute the js.erb file with the same name as your method.
And in the shortlist.js.erb, you may write something like:
$('#shortlist').html('<%= escape_javascript(render "pages/shortlist_fields")%>');
Besides, you can also call the same js.erb file.
In the unshortlist method, you can do it like that:
respond_to do |format|
format.html {redirect_to products_path }
format.js {render :action=>'shortlist'}
end

Resources