I have a projects/show.html.erb page. A project has_many project_messages and from the projects/show.html.erb page, a user can create a new project_message successfully, however, when the new project_message is created through a _formpartial, the page refreshes.
I want to use :remote => true to add project_messages to the project without having to refresh the page.
Please see the code I used below. This does not work and the page still refreshes. I am new to rails so any help would be greatly appreciated.
Please see the code for each file below
In projects/show.html.erbto display the project_message and create a new project_message, I have the following code which is successful:
<div class="au-chat au-chat--border">
<div class="au-message-list">
<% #project.project_messages.each do |project_message| %>
<%= render partial: 'project_messages/project_message', locals: { project_message: project_message } %>
<% end %><br>
</div>
<div class="au-chat-textfield">,
<%= render partial: 'project_messages/form', locals: { project_message: #project_message } %>
</div>
</div>
In the project_messages_controller.rb file the create method is as follows, I have added format.js { }
def create
#project_message = ProjectMessage.new(project_message_params)
#project_message.user_id = current_user.id if current_user
#project_message.project_id = current_user.team.project_id if current_user
respond_to do |format|
if #project_message.save
format.html { redirect_to #project_message.project }
format.json { render :show, status: :created, location: #project_message }
format.js { }
else
format.html { render :new }
format.json { render json: #project_message.errors, status: :unprocessable_entity }
end
end
end
The project_message _form partial then includes the :remote => true
<%= form_with(model: project_message, local: true, :remote => true) do |form| %>
<% if project_message.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(project_message.errors.count, "error") %> prohibited this project_message from being saved:</h2>
<ul>
<% project_message.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form.text_field :pMessage, id: :project_message_pMessage, :class => 'au-input au-input--full au-input--h65', placeholder: 'Type a message' %>
<div class="actions" >
<%= form.submit "Send" %>
</div>
<% end %>
I then created a new create.js.erb file in views/project_messages/create.js.erb and added the following code:
# confirm file called
console.log('create.js.erb file');
# add new comment to end of comments section
$("#project_message").append("<%= j render(#project_message) %>");
With the code above, the page still refreshes.
When I remove local: true from the project_message _form partial, it does not refresh and creates the model but the projects/show.html.erb view is not updated!
I used the following link here and also other posts on stackoverflow
respond_to do |format|
format.js { render 'project_messages/create.js'}
end
it seems you are using Rails 5
remove remote: true and local: true from your code
read about this in here
and make sure that you a html element with id = project_message
your code is $("#project_message").append("<%= j render(#project_message) %>");
so check your HTML code , is there any element with ID like that
you can use traditional form_for http://guides.rubyonrails.org/working_with_javascript_in_rails.html#remote-elements
update below code in your views
<%= form_for project_message, :remote => true do |form| %>
and make sure that you a html element with id like <div class="au-message-list" id="project_message">
Related
I currently have a basic to do list app that displays tasks "to do" and also tasks "completed" on the index page of the app. The model "tasks" has the attribute "completed" which I have a link to in the show page of the task:
<%= link_to "Completed", complete_task_path, method: :patch%>
The lists update on page refresh, but I'm having trouble actually making an AJAX request to update this information on the index page.
I'm unsure as to what my url should be, as I've tried to use the one provided using "rake routes" in the console.
My complete.js.erb:
$(document).ready(function() {
console.log("working");
$('.task_submit_box').click(function() {
$.ajax({url: '/tasks/:id/complete', success: function(result) {
$('.task_area').html(result);
console.log(result);
}});
});
});
My html for displaying the tasks:
<ul class="wrapper_task_list">
<% #task.each do |task| %>
<% if task.completed == false %>
<li>
<div class="task_area", id="incomplete_task_area">
<%= link_to task.title, task_path(task), class: 'wrapper_task_name'%>
<%= form_for task, remote: true do |f| %>
<%= f.check_box :completed, class: 'task_check_box' %>
<%= f.submit 'update', class: 'task_submit_box' %>
<% end %>
</div>
</li>
<% end %>
<% end %>
</ul>
And my complete method in my controller:
def complete
#task = current_user.tasks.find(params[:id])
#task.update_attribute(:completed_at, Time.now)
#task.update_attribute(:completed, true)
respond_to do |format|
format.js
format.html
end
redirect_to root_path
end
regarding the route, this is what is displayed for "rake routes" command:
complete_task PATCH /tasks/:id/complete(.:format) tasks#complete
I'm completely lost as to how to make this request go through ajax without throwing back a 406 error. I am trying to add an item to a cart with ajax, and the item does get added and after a refresh the cart is updated. All I receive as an xhr notice with the 406 error. Any help is highly appreciated.
Product Controller
class ProductsController < ApplicationController
def index
#products = Shoppe::Product.root.ordered.includes(:product_categories, :variants)
#products = #products.group_by(&:product_category)
end
def show
#product = Shoppe::Product.root.find_by_permalink(params[:permalink])
end
def buy
#product = Shoppe::Product.root.find_by_permalink!(params[:permalink]) || params[:variant] ? Shoppe::Product.root.find_by_permalink!(params[:permalink]).variants.find(params[:variant].to_i) : #product
current_order.order_items.add_item(#product, 1)
respond_to do |format|
format.js
end
end
end
Show.html.erb
<h2><%= #product.name %></h2>
<% if #product.default_image %>
<%= image_tag #product.default_image.path, :width => '200px', :style => "float:right" %>
<% end %>
<p><%= #product.short_description %></p>
<p>
<% if #product.has_variants? %>
<% #product.variants.each do |v| %>
<%= form_tag product_path(#product.permalink, #product.permalink, :variant => v.id ),id: '#submit-form', remote: true do %>
<%= submit_tag 'Add to basket', :disabled => !v.in_stock? %>
<% end %>
<% end %>
<% else %>
<b><%= number_to_currency #product.price %></b>
<%= link_to "Add to basket", product_path(#product.permalink), :method => :post %>
<% end %>
</p>
<hr>
<%= simple_format #product.description %>
<hr>
<p><%= link_to "Back to list", root_path %></p>
routes.rb
Rails.application.routes.draw do
mount Shoppe::Engine => "/admin"
get "product/:permalink", to: "products#show", as: "product"
post "product/:permalink", to: "products#buy", as: "buy"
get "basket", to: "orders#show"
delete "basket", to: "orders#destroy"
root to: "products#index"
end
products.js.erb
$(document).ready(function() {
var data = $('#submit-form').attr('action')
$.ajax({
type: 'POST',
url: data
});
});
Looking up what format.js does, I found this: rails respond_to format.js API
It seems format.js in your buy action will render the buy.js file. You haven't shown this file, so I'm figuring it doesn't exist.
I'm figuring what you're trying to do is render json, which is simple enough. You could replace:
respond_to do |format|
format.js
end
with this:
render json: <your object>.to_json
make sure to strip any private data before sending the response.
By the way, you should probably be attaching a callback to your $.ajax call.
I've a Rails app and I run rails g scaffold friends name. Inside my Friend model, I put this:
class Friend < ActiveRecord::Base
validates_presence_of :name
end
and this is my new and create action inside FriendsController:
def new
#friend = Friend.new
end
...
def create
#friend = Friend.new(friend_params)
respond_to do |format|
if #friend.save
format.html { redirect_to #friend, notice: 'Friend was successfully created.' }
format.json { render :show, status: :created, location: #friend }
else
format.html { render :new }
format.json { render json: #friend.errors, status: :unprocessable_entity }
end
end
end
and this is my form partial for friends:
<%= form_for(#friend) do |f| %>
<% if #friend.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#friend.errors.count, "error") %> prohibited this friend from being saved:</h2>
<ul>
<% #friend.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<script type="text/javascript">
$(function(){
console.log("Hello world!");
});
</script>
As you can see, I've jQuery $(document).ready() at bottom of my form which log Hello world! when I load the form.
When I submit the form without name, it render again the new template but not calling that jQuery $(document).ready().
Demo:
How do I trigger jQuery $(document).ready() again inside the render new partial when validation(s) failed?
And why this happened?
In Rails4 turbolinks concept will come by default. So $(document).ready() will not load properly, so u can follow below options,
var ready;
ready = function() {
console.log("Hello world!");
};
$(document).ready(ready);
$(document).on('page:load', ready);
Or
$(document).on('ready page:load', function () {
console.log("Hello world!");
});
Or
You can use jquery.turbolinks gem to avoid this problem
Or
You can use other turbolinks events to solve the problem.
Hope it will solve your problem.
What would be the best way to update a record and display a flash success notice without leaving the page?
Here is part of my code but it redirects back to root path:
View
<%= form_for #user, url: record_testimonial_path(#user) do |f| %>
<%= f.text_area :testimonial %>
<%= f.submit "Submit"%>
<% end %>
Controller
def record_testimonial
#user.update_attribute(:testimonial, params[:user][:testimonial])
flash[:success] = "Thank you!"
redirect_to root_path
end
You can redirect back:
redirect_to :back, flash: { success: t('flash.thank_you') }
Or you have to do it via remote:
<%= form_for #user, url: record_testimonial_path(#user), remote: true do |f| %>
<%= f.text_area :testimonial %>
<%= f.submit "Submit"%>
<% end %>
And in the controller:
def record_testimonial
if #user.update_attribute(:testimonial, params[:user][:testimonial])
respond_to do |format|
format.js { render 'record_testimonial', layout: false }
end
else
render nothing: true # This will silently fail. Probably not intended.
end
end
And then the record_testimonial.js.erb:
$('#some_id').html('<%= j render "some_partial", user: #user %>');
These are the most common and I would say sensible ways. If you use ajax don't forget to manually display the flash message, should be 1 line of JS.
Best way to avoid a page refresh completely would be to set the form to use :remote => true like this
<%= form_for #user, url: record_testimonial_path(#user), :remote => true do |f| %>
and then respond accordingly in the controller:
def record_testimonial
respond_to do |format|
if #user.update_attribute(:testimonial, params[:user][:testimonial])
render :success
else
render :error
end
end
end
You would need a corresponding template for success and error here, with which to handle the displaying of a success or error message.
For further info, look here.
I have a Rails app with listing of leads in a table. In one of the collumns I display status of a lead in a drop down menu. I want to enable changing this status of the lead on changing the value selected in the drop down.
This is what I tried:
The code to display the form in a table cell:
<% #leads.each do |lead| %>
<tr>
<td><%= lead.id %></td>
<td><%= form_for(lead,:url => 'update_lead_status') do |f| %>
<div class="field">
<%= f.select :status, ["to_call","called","confirmed","lite"], :selected => lead.status, onchange: "this.form.submit();" %>
</div>
<% end %>
</td>
my update_lead_status method in leads controller:
#PUT
def update_lead_status
#lead = Lead.find(params[:id])
respond_to do |format|
# format.js
if #lead.update_attributes(params[:lead])
format.html { redirect_to leads_url, notice: 'Lead was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #lead.errors, status: :unprocessable_entity }
end
end
end
Also I want the submission to be Ajax style without refreshing.
Set form id and then submit form
<%= form_for(lead,:url => 'update_lead_status',:html=>{:id=>'lead_form'}) do |f| %>
<%= f.select :status, ["to_call","called","confirmed","lite"], :selected => lead.status, onchange: "$('#lead_form').submit();" %>
<% end %>