How to display validation error in rails using AJAX - javascript

I need to display the validation error of my post model. I have used AJAX call to create a post into the index page of the post. So that when the NewPost button is clicked it will display the new post form partial into the index page. While creating the post in index page if there is any validation errors found, the errors are displayed and it renders the new post form partial in js format again so that the new post form appears twice along with the validation error.
Posts controller:
def create
#post = #topic.posts.build(post_params)
#post.user = current_user
respond_to do |format|
if #post.save
# Success
else
format.js { render 'posts/new' }
end
end
end
Create.js.erb file:
alert("Post created Successfully");
$('.new_post').hide();
$('.new_one').show();
$('.post_div').prepend('<%= j render #post %>');
Index.html.erb file:
<div class="container" >
<% if params[:topic_id].present? %>
<h2 align="center"><span class="em-text"><%= #topic.topicname %> Posts</span></h2><hr>
<%= link_to "New Post", new_topic_post_path, :class => 'btn btn-primary new_one' ,remote: true%> <br><br><br>
<% else %>
<h2 align="center"><span class="em-text">All Posts</span></h2><hr>
<% end %>
<div class="post_div">
<%= render #posts %>
</div>
<%= will_paginate #posts, renderer: BootstrapPagination::Rails %>
</div>
Post partial for new post form:
<%= form_for [#topic, #post],remote: true,html: {multipart: true}, url: topic_posts_path do |f| %>
<% if #post.errors.any? %>
<% #post.errors.full_messages.each do |msg| %>
<div class="alert alert-danger"><%= msg %></div>
<% end %>
<% end %>
<div class="form-group">
<%= f.label "Title" %><br/>
<%= f.text_field(:title,{:class => 'form-control', :placeholder => 'Enter the Title'}) %>
</div>
<div class="form-group">
<%= f.label "Body" %><br/>
<%= f.text_area(:body, {:class => 'form-control', :placeholder => 'Enter the Post Body'}) %>
</div>
<div class="form-group">
<%= f.submit({:class => 'btn btn-primary'})%>
</div>
<% end %>
new.js.erb file:
$('.new_one').hide().after("<%= j render 'form' %>")

Use can like this
<% if #post.errors.any? %>
alert("ERROR(S):\n<%= j #post.errors.full_messages.join("\n") %>")
Check the post whether it has any errors if error exists alert the error else do something

Related

Update checkbox options using ajax in Rails 5

A little explanation of the app. It's a tour registration system for a multi-campus organization. Someone should be able to come in and select a campus from a select box and have the "options" checkboxes and "tour dates" radio buttons update to be campus specific.
I've got the script triggering when someone changes the select box but it keeps returning a 404 when I go to the path and the url looks really wonky. Also I know I'm going to run into trouble when I try to .html replace the section with new options. Ok without further ado, here's the code. Any guidance would be appreciated!
_form.html.erb
...
<div class="field">
<%= label_tag 'Campus' %>
<%= select_tag 'campuses', options_from_collection_for_select(#churches, 'id', 'name', selected: (#registration.event.church.id unless #registration.event.nil?) )%>
</div>
<div class="field">
<%= label_tag 'Areas of Interest' %>
<div id="options_container">
<%= f.collection_check_boxes :option_ids, #options, :id, :ministry_area do |b| %>
<div class="collection-check-box">
<%= b.check_box %>
<%= b.label %>
</div>
<% end %>
</div>
</div>
<div class="field">
<%= label_tag 'Tour Dates' %>
<div id="events_container">
<%= f.collection_radio_buttons(:event_id, #events, :id, :event_datetime) do |b| %>
<div class="radio">
<%= b.radio_button + " " + b.label %>
</div>
<% end %>
</div>
</div>
<div class="actions">
<%= f.submit params[:action] == 'edit' ? "Update Registration" : "Register", class: 'button' %>
</div>
<% end %>
<script>
$(document).ready(function () {
$('#campuses').change(function () {
$.ajax({
url: "<%= update_campus_options_and_events_path %>",
data: {
campus_id: $('#campuses').val()
},
dataType: "script"
});
});
});
</script>
routes.rb
Rails.application.routes.draw do
resources :registrations
root 'registrations#index'
get 'update_campus_options_and_events', to: 'registrations#update_campus_options_and_events'
end
registrations_controller.rb
...
def update_campus_options_and_events
#events = Event.find(params[:campus_id])
#options = Option.find(params[:campus_id])
respond_to do |format|
format.html
format.js {}
end
end
...
update_campus_options_and_dates.js.erb
console.log('Options changed via ajax');
$('#options_container').html("<%= escape_javascript(<%= f.collection_check_boxes :option_ids, #options, :id, :ministry_area do |b| %>) %>");
$('#events_container').html("<%= escape_javascript(<%= f.collection_radio_buttons(:event_id, #events, :id, :event_datetime) do |b| %>) %>");

How to show a notice after submitting a simple form

I'm using Simple Form and Ajax and I want to show a notice(it can be flash) something like "Successfully Submitted", after successful submission of a form. How can I achieve this?
This my controller:
def create
#order = current_order
#order_item = #order.order_items.new(order_item_params)
#order.user_id = current_user.id
#order.save
session[:order_id] = #order.id
end
and my form in views:
<%= form_for OrderItem.new, html: {class: "add-to-cart"}, remote: true do |f| %>
<div class="input-group">
<%= f.hidden_field :quantity, value: 1, min: 1 %>
<div class="input-group-btn">
<%= f.hidden_field :product_id, value: product.id %>
<%= f.submit "Add to Cart", data: { confirm: 'Are you sure?'}, class: "btn btn-default black-background white" %>
</div>
</div>
<% end %>
</div>
You can do it responding to a javascript request when form is submitted.
Controller:
# app/controllers/mycontroller.rb
def create
#order = current_order
#order_item = #order.order_items.new(order_item_params)
#order.user_id = current_user.id
#order.save
session[:order_id] = #order.id
respond_to do |format|
format.js { flash[:notice] = "Created order" }
end
end
And then create a view to show the message:
# app/mycontroller/create.js.erb
<% flash.each do |key, value| %>
$('.add-to-cart').append('<%= j content_tag :div, value, class: "flash #{key}" %>')
<% end %>
It should work!
You can use bootstrap alert to achieve it.
Controller:
def create
#order = current_order
#order_item = #order.order_items.new(order_item_params)
#order.user_id = current_user.id
if #order.save
flash[:success] = "Successfully Submitted"
end
session[:order_id] = #order.id
end
You can display that flash message wherever you want to using this
View:
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>"><%= message %></div>
<% end %>

Saving Nested Data Before Parent is Assigned an ID

I have a Resume model and an Education model. Education belongs_to resume and resume has_many educations.
I'm currently using a form in Resume's show.html.erb view to enter data for educations just to make sure it works.
In my routes.rb file I have:
resources :resumes do
resources :educations
end
In my educations_controller.rb file I have this:
def create
#resume = Resume.find(params[:resume_id])
#education = #resume.educations.build(education_params)
respond_to do |format|
if #education.save
format.html { redirect_to #resume, notice: 'Education was successfully created.' }
format.json { render :show, status: :created, location: #education }
else
format.html { render :new }
format.json { render json: #education.errors, status: :unprocessable_entity }
end
end
end
This allows me, in my views/resumes/show.html.erbto have the following:
<%= form_for [#resume,Education.new] do |f| %>
<div class="field">
<%= f.label :sectionTitle %><br>
<%= f.text_field :sectionTitle %>
</div>
<div class="field">
<%= f.label :completed %><br>
<%= f.date_select :completed %>
</div>
<div class="field">
<%= f.label :degree %><br>
<%= f.text_field :degree %>
</div>
<div class="field">
<%= f.label :school %><br>
<%= f.text_field :school %>
</div>
<div class="field">
<%= f.label :summary %><br>
<%= f.text_area :summary %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
This is currently working and allows me to enter multiple educations per Resume.
The issue is, I first have to create the resume entry before creating an education entry because the education entry depends on the resume_id integer.
How can I re structure my code so that I can create multiple education entries for a specific resume that doesn't yet have an ID so that essentially, on submit the resume is assigned an ID then any subsequent educations are attached to the given resume_id and given their own education ID?
I suspect I'll probably have to use javascript which is fine, but even so, I'm not sure what to do once intercept the default form action.
This is just little example but it works totally fine.
In routes.rb
post 'add_resume_education' => 'resumes#twince'
In resumes_controller.rb, in your case. Use your own MODEL like resume and education and change passing params too.
def twince
resume = Resume.create!(title: params[:data][:category_title])
post = resume.educations.create!(sectionTitle: params[:data][:educations][:sectionTitle])
redirect_to :back, notice: 'Yeah Created'
end
in HTML page:
<%= form_for :data, url: add_resume_education_path do |f| %>
<div class="field">
<%= f.label :category_title %>
<%= f.text_field :category_title %>
</div>
<br>
<div class="field">
<%= f.fields_for :educations do |edu| %>
<div class="field">
<%= edu.label :sectionTitle %><br>
<%= edu.text_field :sectionTitle %>
</div>
<% end %>
</div>
<br>
<%= f.submit 'create' %>
<% end %>
Also here quite good source, Nested Form

rails4 js response XSS

I have a rails4 app. If I submit <script>alert('haha')</script> in the form then alert gets displayed, so it doesn't escape js (despite of having <%= j render #post %>), so my app is not protected from XSS.
Why is this happening? What should I do?
controller
def create
#post = current_user.posts.new(post_params)
#post_comment = PostComment.new
if #post.save
respond_to do |format|
format.html { redirect_to #post, notice: "Post saved!" }
format.js
end
else
.......
_form
<%= form_for #post, remote: true, method: :post, class: "post-create-form" do |f| %>
<div class="alert alert-danger" style="display:none">
<ul class="errors" style="display:none">
<%= render 'layouts/error_messages', object: f.object %>
</ul>
</div>
<div class="form-group">
<%= f.text_area :body, placeholder: "Share something useful..", class: "form-control post-create-body" %>
</div>
<div class="form-group">
<%= f.button "Share", class: "btn btn-primary btn-create-post", data: {disable_with: "<i class='fa fa-spinner fa-spin'></i> Saving..."} %>
</div>
create.js.erb
$("ul.errors").html("");
<% if #post.errors.any? %>
$('.alert-danger').show();
$('ul.errors').show();
<% #post.errors.full_messages.each do |message| %>
$("ul.errors").append($("<li />").html("<%= message.html_safe %>"));
<% end %>
<% else %>
$('ul.errors').hide();
$('.alert-danger').hide();
$('.post-index').prepend('<%= j render #post %>');
$('.post-create-body').val('');
$('.btn-create-post').prop('disabled',true);
<% end %>

Confirmation message - Javascript rails application

I'm a bit new to rails and I'm just trying to display a confirmation message when a "Proposition" (created model) has been inserted. For this, I'm using a javascript functionality embedded to rails.
Unfortunately, when I click and submission button, the proposition is correctly inserted but I can't find a way to display this confirmation message (like "proposition correctly submitted" for example)...
Below the code that I'm using :
Proposition Model :
class Proposition < ActiveRecord::Base
belongs_to :ad
attr_accessible :email, :name, :phone, :price
validates_presence_of :name or :price or :email or :phone
end
Create method in controller :
def create
#ad = Ad.find(params[:ad_id])
#proposition = #ad.propositions.create(params[:proposition])
respond_to do |format|
if #proposition.save
format.html { redirect_to ad_path(#ad), notice: 'Proposition was successfully created.' }
format.json { render json: ad_path(#ad), status: :created, location: #proposition }
format.js
else
format.html { render action: "new" }
format.json { render json: #proposition.errors, status: :unprocessable_entity }
format.js { render action: "new" }
end
end
end
_form.html.erb :
<%= form_for [#ad, #ad.propositions.build], :remote => true do |f| %>
<% if #proposition.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#proposition.errors.count, "error") %> prohibited this proposition from being saved:</h2>
<ul>
<% #proposition.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :Prénom %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :"Adresse mail" %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :Téléphone %><br />
<%= f.text_field :phone %>
</div>
<div class="field">
<%= f.label :"Prix proposé" %><br />
<%= f.text_field :price %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
create.js.erb :
$('#new_proposition').fadeOut(1000);
new.js.erb :
$('#new_proposition_link').hide().after('<%= j render("form") %>');
Thanks for your help !
Since you already have a create.js.erb file, you can use JS to display an alert message or insert a confirmation message into the page like so,
# app/views/.../create.js.erb
$('#new_proposition').before('<p>Proposition correctly submitted!</p>');
$('#new_proposition').fadeOut(1000);
This inserts the <p>Proposition correctly submitted!</p> before the #new_proposition element. You may want to insert it somewhere else since this element will disappear.

Categories