AJAX not working in Rails same-page update - ruby-on-rails

I am trying to build a Q&A app with Ajax on the Index.html.erb. I manage to get the form remotely loading, but when saving the records, the AJAX does not work and the user is taken to the normal show.html.erb. Apart from the Ajax not kicking off, everything works well.
My code is as below:
index.html.erb (Contain a partial for input, and a partial for results)
<div>
<h3 class="section_title"> Q&A </h3>
<hr>
<div id="qanda-form" style="display:none;"> </div>
</div>
<div id="qandas">
<%= render 'qandas/qanda' %>
</div>
_qanda.html.erb (is the partial for results)
<% #qandas.each do |my_qanda| %>
<div class="col-md-9">
<div>
Created <%= local_time(my_qanda.created_at) %>, by <%= User.find_by(id: my_qanda.user_id).full_name %>
</div>
</div>
<% end %>
_form.html.erb (is the input form - has nested form via Cocoon)
<%= simple_form_for #qanda, remote: true do |f| %>
<%= f.error_notification %>
<%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
<div class="col-md-12 form-inputs">
<div class="col-md-8">
<%= f.input :title, label: 'Q&A Title:' %>
</div>
</div>
<div class="qandasquestions">
<%= f.simple_fields_for :qandasquestions do |builder| %>
<% render 'qandas/qandasquestion_fields', f: builder %>
<% end %>
<div class="links btn-group" style="min-height: 34px !important">
<%= f.button :submit, "Publish Q&A", class: "btn btn-default" %>
<%= link_to_add_association 'Add Question', f, :qandasquestions, class: 'btn btn-default', data: {association_insertion_node: '.qandasquestions', association_insertion_method: :append} %>
<%= link_to 'Back', qandas_path, class: "btn btn-default" %>
<%= f.input :company, :as => :hidden, :input_html => {:value => current_user.company} %>
</div>
</div>
<% end %>
Controller:
def index
#qandas = Qanda.all
respond_to do |format|
#qandas = Qanda.all
format.html
format.json
end
end
def create
#qanda = current_user.qandas.build(qanda_params)
respond_to do |format|
if #qanda.save!
#qandas = Qanda.all
format.html { redirect_to #qanda, notice: 'Qanda was successfully created.' }
format.json {render :layout => false}
else
format.html { render :new }
format.json { render json: #qanda.errors, status: :unprocessable_entity }
end
end
end
create.js.erb
$('#qandas').html("<%= j render partial: 'qandas/qanda' %>");
$('#qanda-form').slideUp(350);
new.js.erb
$('#qanda-form').html("<%= j render 'qandas/form' %>");
$('#qanda-form').slideDown(350);
Anybody can see why the Ajax does not kick off please? why am I redirected to the traditional SHOW page please?

Try updating your code to this and let me know if it's working?
def create
#qanda = current_user.qandas.build(qanda_params)
if #qanda.save!
#qandas = Qanda.all
else
#errors = #qanda.errors
end
end

Related

Rails 7 turbo-stream broadcast to specific channel not working

I have a Post model and Comment, and Post has_many Comment and I wanna real-timely update the comment when you are in a specific post, meaning, the comments live-updating should only visible when multiple users are in the same post, for example: in posts/6
For View I have:
<div>
<p>
<strong>Title:</strong>
<%= post.title %>
</p>
<p>
<strong>Content:</strong>
<%= post.content %>
</p>
<p>
<strong>User:</strong>
<%= post.user.username %>
</p>
</div>
<hr/>
<%= form_for [post, Comment.new] do |f| %>
Body: <%= f.text_area :body, rows: 5, cols: 20 %>
<%= f.submit "Submit" %>
<% end %>
<hr/>
<h1>Comments:</h1>
<%= turbo_stream_from post %>
<%= turbo_frame_tag post do %>
<div id="<%= dom_id(post) %>">
<% post.comments.includes(:user).each do |comment| %>
<%= render comment %>
<% end %>
</div>
<% end %>
In Comment#create action I have:
post = Post.find(params[:post_id])
#comment = post.comments.new(comment_params)
#comment.user_id = current_user.id
respond_to do |format|
if #comment.save
format.turbo_stream { render turbo_stream: turbo_stream.prepend("post_#{post.id}", partial: "comments/comment", locals: { comment: #comment }) }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
In Comment model I have:
after_create_commit {
broadcast_prepend_to(target: "post_#{self.post.id}")
}
And in terminal I can see
[ActionCable] Broadcasting to : "<turbo-stream action=\"prepend\" target=\"post_6\"><template> <div>\n <p>\n <strong>Title:</strong>\n adsd\n </p>\n\n <p>\n <strong>Content:</strong>\n Asda\n </p>\n\n <p>\n <strong>User:</strong>\n Super Saiyan Vegeta\n </p>\n </div>\n\n <hr/>\...
Which is correct, but the comments list in a specific post still not updating, and I do see I have id="post_6" in the view...can someone tell me why? Thanks.
Try to change
<div id="<%= dom_id(post) %>">
to
<div id="post_<%= post.id %>">
And use such method in controller
if #comment.save
#comment.broadcast_prepend_to to post, target: "post_#{post.id}", partial: "comments/comment", locals: { comment: #comment }
end
instead of broadcast from model

Why Ajax call is responding after a page refresh in rails 4?

Suppose I have defined my create action like this:
def create
#appointment = Appointment.find(params[:appointment_id])
#note = #appointment.notes.new(notes_params)
#note.user_id = current_user.id
respond_to do |format|
if #note.save
format.html { redirect_to appointment_path(#appointment), notice: "Saved successfully" }
format.js
else
format.html { render 'new', notice: "Try again" }
format.js
end
end
end
My create.js.erb is like this:
$("#note_field").html("<%= j render partial: 'note', locals: {note: #note} %>");
Here is my form:
<%= form_for([#appointment, #appointment.notes.build({user: current_user})], remote: true) do |f| %>
<div>
<% if #note && #note.errors.any? %>
<% #note.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
<% end %>
</div>
<div class="field">
<%= f.label :Description %><br>
<%= f.text_area :description, required: true %>
</div>
<div>
<%= f.submit class: "note-button" %>
</div>
<% end %>
Here, note is partial form. How to make it work without a page refresh?

Validation errors are not displaying at multipart form in rails

I have a model BookingPost that has many Reservations.
In booking_posts/show.html.erb I have:
<div class="card-action">
<%= form_for([#reservation.booking_post, #reservation], html: {multipart: true}, class: "col s12") do |f| %>
<% if #reservation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reservation.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #reservation.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="col s6">
<%= f.label :start %>
<%= f.date_field :start, placeholder: "start time", class: "datepicker" %>
</div>
<div class="col s6">
<%= f.label :end %>
<%= f.date_field :end, placeholder: "end time", class: "datepicker" %>
</div>
<div class="col s6">
<%= f.label :reservation_time %>
<%= f.time_field :reservation_time, placeholder: "time", class: "timepicker", id: "timepicker", type: "time" %>
</div>
<div class="input-field col s6">
<%= f.label :name %>
<%= f.text_field :name, class: "validate" %>
</div>
<div class="input-field col s6">
<%= f.label :email %>
<%= f.text_field :email, class: "validate" %>
</div>
<div class="input-field col s6">
<%= f.label :phone_number %>
<%= f.text_field :phone_number, class: "validate" %>
</div>
<div class="waves-effect waves-light btn">
<%= f.submit t(:submit_reservation)%>
</div>
<% end %>
<br>
</div>
booking_posts_controller:
# GET /booking_posts/1
# GET /booking_posts/1.json
def show
#booking_picture = #booking_post.booking_pictures.build
#booking_pictures = #booking_post.booking_pictures
#reservation = #booking_post.reservations.build
#reservations = #booking_post.reservations
end
reservations_controller:
# GET /reservations/new
def new
#reservation = Reservation.new
end
def create
#booking_post = BookingPost.find(params[:booking_post_id])
#email= User.where(admin: true).first.email
#reservation = #booking_post.reservations.build(reservation_params)
respond_to do |format|
if #reservation.save
#saved_reservation = #reservation
format.html { redirect_to :back, notice: 'Reservation was successfully created.' }
format.json { render :show, status: :created, location: #reservation }
ReservationMailer.fresh_message(#saved_reservation, #email).deliver_now
else
format.html {redirect_to :back
flash[:info] = #reservation.errors.full_messages do |m|
m
end}
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
But I can't see any validation errors, even like presence: true.
Seems like I don't have correct #reservation, because I have a deal with Array in my form_for. Help me please to solve this issue, thanks!
The reason you are not seeing validation errors is because you are issuing a redirect_to :back when validations fails instead of rendering :new action which already includes any errors you might have inside the #reservation instance object.
Also you were trying to add the error messages into the flash message while trying to display them using the #reservation object.
this should be the correct else clause
else
format.html { render :new }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end

How to use partials with more than one collection in rails

I want to use two collection #ad_item and #user in my partial. Here is my index erb...
<% if #ad_items.any? && #user.any? %>
<%= render partial: 'yourads/ad_item', collection: {#ad_items,#user} %>
<% end %>
and here is my controller ...
def index
#ad_items = Yourad.all
#user = User.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #yourads }
end
end
and here is my _ad_item.erb.html partial
<span class="date"><%= ad_item.created_at.to_date() %></span>
<span class="location"><%= ad_item.title %></span>
<div style="float:left"><%= ad_pic #user,ad_item %></div>
<div class="description"><%= ad_item.description %></div>
My helper function is ..
def ad_pic(user,ad)
cl_image_tag("Ad#{user.id}#{ad.id}.jpg", :version => rand(1000000000), :alt => "Ad pic",:width => 70, :height => 70, :crop => :fill)
end
it gives syntax error in ..
<%= render partial: 'yourads/ad_item', collection: {#ad_items,#user} %>
<%= render partial: 'yourads/ad_item', collection: #ad_items ,
locals: {users: #users} %>
and in view
<% for user in users %>
<span class="date"><%= ad_item.created_at.to_date() %></span>
<span class="location"><%= ad_item.title %></span>
<div style="float:left"><%= ad_pic user,ad_item %></div>
<div class="description"><%= ad_item.description %></div>
<% end %>
see Passing Local Variables
<%= render partial: 'yourads/ad_item', :locals => {:ad_items=>#ad_items,:user => #user }%>
you can access #ad_items as ad_items and #user as user in your yourads/ad_item partial

After submit form I want to stay in the same page and display :notice messages

All my code is working nicely, I want to render the same page :new after a user submits a form with your order. The problem is about the :notice message that I want to display Pedido enviado com sucesso. in the page after a submission but it doesn't work. My validation error messages are displayed nicely but I don't know why my success message doesn't.
Any tips?
(Sorry about my code indentation)
My pedidos_controller goes down:
class PedidosController < ApplicationController
def new
#pedido = Pedido.new
1.times do
pessoa = #pedido.build_pessoa
produto = #pedido.produtos.build
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #pedido }
end
end
def create
#pedido = Pedido.new(params[:pedido])
respond_to do |format|
if #pedido.save
PedidosMailer.delay.registro_do_pedido(#pedido)
PedidosMailer.delay.email_para_cotar_produtos(#pedido)
format.html { redirect_to action: "new", notice: 'Pedido enviado com sucesso.' }
format.json { render json: #pedido, status: :created, location: #pedido }
else
format.html { render action: "new" }
format.json { render json: #pedido.errors, status: :unprocessable_entity }
end
end
end
end
my new.html.erb view:
<p id="notice"><%= notice %></p>
<%= render 'form' %>
my _form.html.erb view:
<%= form_for(#pedido, :html => { :class => "form-contato"}) do |f| %>
<% if #pedido.errors.any? %>
<div id="error_explanation">
<h2>Ocorreram <%= pluralize(#pedido.errors.count, "erro") %></h2>
<ul>
<% #pedido.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="span4">
<h1>Dados pessoais</h1>
<%= f.fields_for :pessoa do |builder| %>
<%= render 'pessoa_fields', f: builder %>
<% end %>
</div>
<div class="span8">
<h1>Ítens</h1>
<%= f.fields_for :produtos do |builder| %>
<%= render 'produto_fields', f: builder %>
<% end %>
</div>
<div class="span10">
<%= link_to_add_fields "Adicionar mais produtos", f, :produtos %>
</div>
<%= button_tag "Enviar", class: "btn btn-red span10", name: "commit" %>
</div>
<% end %>
my _pessoa_fields.html.erb view:
<fieldset>
<%= f.text_field :nome, class: "span4", placeholder: "Nome" %>
<br />
<%= f.text_field :telefone, class: "span4", placeholder: "Telefone" %>
<br />
<%= f.text_field :email, class: "span4", placeholder: "Email" %>
</fieldset>
my _produto_fields.html.erb view:
<% #lista_de_produtos = ["Qualibom standard", "Qualibom premium", "Bomdemais standard", "Bomdemais premium"] %>
<fieldset class="campos-produtos span10">
<div class="span3">
<%= f.select :nome, options_for_select(#lista_de_produtos, :selected => f.object.nome), :prompt => 'Selecione um produto' %>
</div>
<div class="span3">
<%= f.text_field :quantidade, class: "span3", placeholder: "Quantidade" %>
</div>
</fieldset>
You need to use flash[:notice], not notice, in your view:
<% if flash[:notice] %>
<p id="notice"><%= flash[:notice] %></p>
<% end %>
When you pass a message via the notice: parameter of redirect_to, it's placed into the flash array, which is a special pseduo-session which persist for a single request:
From the ActionController::Redirecting documentation:
It is also possible to assign a flash message as part of the redirection. There are two special accessors for the commonly used flash names alert and notice as well as a general purpose flash bucket.

Resources