Displaying flash messages on modal dialog box on submit rails - javascript

I am trying to build the modal box for registering emails addresses in rails.
I have done it but can not able to find the way to display the flash messages on modal dialog box when registration fails.
On submit the box gets closed and message is only getting display on home page. I do not have good knowledge of web or rails, but would be nice if I can get some pointers.
The functionality is working fine expect on fail, dialog box should display the messages on it instead of on home page. I know where is issue in my code but do not know approach to do it. Here is my code for dialog box
<div id="register" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<%= form_for(#email, url: home_esave_path, :html => {class:"model-dialog"}) do |f| %>
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Register</h4>
</div>
<div class="modal-body">
<div class="form-group">
<%= f.text_field :email, class:"form-control", placeholder: "Enter a valid gmail address" %>
</div>
<%= f.show_simple_captcha(:email=>"email", :label => "Human Authentication", :refresh_button_text => "Refresh text", class:"form-control", :placeholder => "Enter the code") %>
<%= f.submit "Register me!", :class => "btn register_button" %>
</div>
<div class="modal-footer" style="text-align:left">
<!-- show in case of success -->
<% if #email.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#email.errors.count, "error") %> prohibited
this email from being saved:
</h2>
<ul>
<% #email.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
<% end %>
</div>
</div>
my controller code to get the messages
def save
#email = Email.new(user_params)
if !user_params.nil?
if #email.save_with_captcha
flash[:success] = "Success! The email address #{#email.email} has been successfully registered. We will contact you as soon as we have available rooms for new beta testers."
redirect_to :action => 'index'
else
if #email.valid?
flash[:error] = "The captcha is not correct, enter again the captcha."
redirect_to :action => 'index'
else
flash[:error] = "You have put invalid #{#email.email}"
redirect_to :action => 'index'
end
end
end
end
Flash messages I am displaying outside this model which is obvious that will be displayed on home page. But I did not find way to display it on model dialog box.
here is how I am displaying the messages
<% flash.each do |type, message| %>
<div class="alert <%= alert_for(type) %> fade in">
<button class="close" data-dismiss="alert">×</button>
<span class="sr-only">Close</span>
<%= message %>
</div>
<% end %>
Thanks for suggestions

Flash is designed as a way to pass data between (controller) actions (see documentation for more information). In your case, you specifically, do not want an action, so I don't think there is a way to do this.
You can however generate a message that looks like your other flash messages using Ajax. Here is one way to do it.
You will need the following components:
Remote call from modal
Add remote: true or :remote => true to your form within the modal. This tells Rails that you want an Ajax call to the server when the form is submitted, not a full page post.
Controller changes
You'll need to respond to formats other than HTML. Something like this:
def save
if !user_params.nil?
#email = Email.new(user_params)
#email.save_with_captcha
respond_to do |format|
format.html { redirect_to #email, notice: 'This should not happen.' }
format.json { render action: 'show' }
format.js { render action: 'show' }
end
end
end
Javascript to insert/clear "flash" error message in your modal
View file - show.js.erb (can be named differently but name should match action above).
$('#build_error').remove();
<% if #email.errors.any? %>
var build_error = "<div class='alert alert-danger' id='build_error'>";
build_error += "The form contains <%= pluralize(#email.errors.count, 'error') %>.";
build_error += "<ul id='error_explanation'>";
<% #email.errors.full_messages.each do |msg| %>
build_error += "<li><%= j msg %></li>";
<% end %>
build_error += "</ul>";
build_error += "</div>";
$(build_error).insertBefore( "#xxxxxx" );
<% else %>
$('#email-modal').modal_success();
<% end %>
Basically, you'll need to clear any previous "flash" error message (the first line) and then either display the new one (you'll need to find somewhere in the DOM to attach it - see xxxxxx) or close the modal. Pretty brute force but it works for me.
Hopefully you get the idea - I doubt any of this will work as is so you will need to understand the concept.

Related

Issue with resetting form after submission using Hotwire & Stimulus.js Rails 6

I've been testing Hotwire, using the demo that was put up by DHH. I have a default rails 6 setup & I know that it re-creates the javascript folder structure from the rails 5 < asset pipeline. The issue I am having is the form will not reset the text field after submission - despite setting up the stimulus controller for using this particular action. How can I reset the form for hotwire after the form is submitted by the user? My code is below
new.html.erb
<%= turbo_frame_tag 'new_conversation_comment', target: '_top' do %>
<%= form_with(model: [#conversation, #conversation_comment],
data: { controller: "reset_form", action: 'turbo:submit-end->reset_form#reset' }, html: {class: 'form-inline'}) do |form| %>
<%= form.submit 'Post', class: 'btn btn-primary mb-2', style: 'float: right;', 'data-reset_form-target': 'button' %>
<div style="overflow: hidden; padding-right: .5em;">
<%= form.text_field :content, class: 'form-control' %>
</div>
<% end %>
_conversation_comment.html.erb
<div class="p-1">
<%= conversation_comment.content %>
</div>
show.html.erb
<div class="p-2">
<%= turbo_stream_from #conversation %>
<%= turbo_frame_tag 'conversation' do %>
....
<% end %>
<div class="conversation-comments-container" id="conversation_comments">
<%= render #conversation.conversation_comments %>
</div>
<hr>
<%= turbo_frame_tag 'new_conversation_comment', src: new_conversation_conversation_comment_path(#conversation), target: :_top %>
</div>
assets/javascripts/controllers/reset_form_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
reset() {
this.element.reset()
}
}
Disclaimer: I'm using Webpack 4.0
Depending on setup underscore between controller name can be an issue. Replacing it with dash worked in my case.
turbo:submit-end->reset-form#reset
Disclaimer: I'm using Webpack 4.0
I ran into the same thing, also using Webpack.
The solution for me was:
Change the underscores to dashes, like Canbey said.
Move the stimulus controller from app/assets/javascripts/controllers/ to app/javascripts/controllers/ (somewhat per the stimulus docs so that webpack imported it properly — my application.js file was importing controllers from that directory rather than app/assets/javascripts.
A half SJR, half Hotwire approach would be this:
Working example here: https://rails-react-bootstrap.herokuapp.com/rooms
new.html.erb
<%= turbo_frame_tag 'new_note' do %>
<%= form_with model: [#room, #note] do |form| %>
<!-- Allow body validation error without message -->
<div class="form-group">
<%= form.rich_text_area :body, class: 'form-control comments', id: 'bodyText' %>
</div><!-- .form-group -->
<div class="form-group d-flex justify-content-center">
<%= form.submit 'Add Note', class: 'btn btn-lg btn-tayberry btn-block' %>
</div><!-- .form-group -->
<% end %>
<% end %>
create_js.erb
// clear note textarea after submit
var input = document.getElementById("bodyText");
input.value = '';
notes_controller
def create
#note = #room.notes.create!(note_params)
# #note.user = current_user
respond_to do |format|
if #note.save
format.turbo_stream
format.html { redirect_to #room }
format.js
else
format.html { render action: 'new' }
end
end
end
If you still need an answer, here is how you can achieve what you need:
In your controller respond to requests like that:
format.html { redirect_to conversations_url }
Note: redirect to the page where new_conversation_comment frame is defined (i.e same page from where you are submitting form). Redirect will happen, but Hotwire will substitute form for you with a new one and append comment where you specified.
It is a bit magic.
I suggest you to check this video:
https://gorails.com/episodes/hotwire-rails?autoplay=1

Rails/JS button onclick to re-render partial without entering into DB

I wish to reload a partial-form with a button(Add). I'm new and don't know how to simply display fields in partial like listings one under the other as many times Add button is clicked. I can't find a relevant example. all AJAX examples mention js.erb when object is saved in DB.
<div class="panel-body">
<%= render partial: "degrees/form", :locals => { :f => f } %>
<%= f.link_to (fa_icon 'plus').to_s + " Add Another Qualification ", render(:partial => 'degrees/form', :locals => { :f => f }), class: "btn btn-primary" %>
</div>
Here, #application is the main form trying to display degree fields. Partial is simply two text-fields- one for selecting educational degree and second its detail.Here's partial
<%= f.fields_for [Degree.new], :url => { :action => "index" } do |ff| %>
<div class = "form-group" }>
<%= ff.select :level, options_for_select(Job::EDUCATION, params[:level]), include_blank: "Select Degree", class: 'span-2' %>
<%= ff.text_field :description, :class => 'span5' %>
</div>
<% ff.submit "Add Another Degree", class: 'btn btn-primary' %>
You don't necessary need to save things to pass away to .js.erb... you can just instantiate...
But if your example is precise, you are missing the remote: true flag for the link... And the partial is not defined on the link... you need to make a view responding to the ajax...
Form example
<div class="panel-body">
<%= link_to new_thing_path, remote: true do %>
<i class="fa fa-plus">
Add another qualification
<% end %>
<div class="new-things-container">
</div>
</div>
Controller answering to the ajax request
class ThingsController < ApplicationController
def new
#thing = Thing.new
respond_with #thing
end
end
View for the ajax request rendering a partial inside a specified div
//views/things/new.js.erb
$('.panel-body .new-things-controller').append("<%= render partial: 'degrees/form', locals: { thing: #thing } %>")

Rails auto clicking a button to refresh div

I'm new to programming and teaching myself Rails as I build an app.
I have a page with a list of jobs. Each job is rendered via a job partial which has a div which renders a status partial via a "Update Status" button with ajax.
The button works as expected and refreshes each job's status when clicked.
I am now trying to make the status div auto-refresh every x seconds.
After trying different methods, I've implemented a javascript which simply periodically refreshes the button (which I can later hide if I want). It was suggested here by #de_an777: Rails 3 - Periodic Refresh of DIV.
This seems to almost work for me.
The problem is that it doesn't refresh ALL jobs in the list. So if I have 2 jobs in the list, I see two refresh operations happening in the server log, but both of them refresh only the first job.
When inspecting the job id for each button element in the browser inspector, they all seem to have the correct id via job[:id].
I've been struggling with this for days, changing my routes and methods but cannot make it work. Hoping that someone can direct me in the right way...
Jobs_controller.rb:
def update
#job = Job.find(params[:id])
#some updating logic
respond_to do |format|
format.js
end
end
index.html.erb:
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>Job List</h1>
</section>
<section class="job_form">
<%= link_to "New Job", upload_path, class: "btn btn-lg btn-primary" %>
</section>
</aside>
</div>
<%= render #jobs %>
_job.html.rb:
<span class="jobs">
<p> Job ID: <%= job.id %></p>
<p> Job Name: <%= job.name != "" ? job.name : "Untitled" %>
<p> Source File: <%= job.source_file %></p>
<% #job = job %>
<div id="status_div_<%= #job.id %>">
<%= render :partial => 'jobs/status', locals: {job: job} %>
</div>
<%= button_to("Update Status", jobs_update_path(id: job.id), remote: true, method: :patch, id: "refresh_#{job[:id]}") %>
</span>
</li>
<script type="text/javascript">
function doSomething() {
$('#refresh_<%= job[:id] %>').click();
}
setInterval('doSomething()',10000);
</script>
routes:
get 'new_job' => 'jobs#new'
get 'upload' => 'jobs#upload'
patch "jobs/update", to: "jobs#update"
resources :jobs
update.js.erb:
$('#status_div_<%= #job.id %>').html("<%= j render :partial => 'status', object: #job, as: :job %>");
_status.html.erb:
<p> Status: <%= job[:status] %></p>

how to open popup box in rails4 link_to

Hi I want to open popup box I had given this in my view
<%=link_to 'show',edit_interview_round_path(round), :remote => true%>
<div id="popup">
</div>
and written this in my controller
def edit
#interview_round = InterviewRound.where(id: params[:id]).first
respond_to do |format|
format.js
end
end
and i am having edit.js.erb
$("#popup").html('<%= escape_javascript(render 'interview_rounds/form') %>');
in interviews_rounds/edit view have written this
<%= render 'form' %>
in interview_rounds/_form view have written this
<%= form_for #interview_round do |f| %>
<div class='modal'>
<%= f.text_field :name, :class => 'form-control' %>
<label for='name'>Name</label>
</div>
<div class='input-field col s12' >
<%= f.text_field :question_1, :class => 'form-control' %>
<label for='name'>Name</label>
</div>
<div class='col s12 center-align'>
<%= button_tag(:class => "btn waves-effect waves-light btn-large custom_btn_gray") do %>
Submit <i class="mdi-content-send right"></i>
<% end %>
</div>
<% end %>
So now when I click on show it does not open popup it shows edit view on same page I want to show it in a popup box please guide me how to do this. Thanks in advance!
Try formatting your partial rendering code thusly:
$("#popup").html("<%= j render( :partial => 'interview_rounds/form' ) %>");
Looks like you have nested single quotes, which is probably the issue.
Your code is currently set to render the partial on the same page in a div with an id of popup.
If you want to render it in a new window, try something like this:
var wind = window.open("", "popupWindow", "width=600,height=600");
wind.document.write("<%= j render( :partial => 'interview_rounds/form' ) %>");
If the form is rendering correctly in the #popup div and you need a modal or overlay effect, you just have to style the popup div as a modal and you're good to go.

Rails Modal Popup after create action

I have a simple vote action in my rails app and i would like a modal popup (like the on in twitter bootstrap) to show after a successful create action. I have a modal view partial, a respond_to block that accepts .js and a create.js.erb file which should in theory be displayed when the create action is called, if im not mistaken?
I just don't quite understand how to wire all of these things together, ( also i assume the javascript is incorrect) any tips would be great thanks!
controller.rb
def create
#vote = Vote.new(params[:vote])
respond_to do |format|
if #vote.save
format.html { redirect_to :back, notice: "Thank you for voting! why not Tweet your vote?" }
format.js <!--should there be a call to a specific file here?-->
else
flash[:error] = "please try again"
redirect_to :back
end
end
end
end
votes/info.html.erb
<div class="modal hide fade">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Thanks for voting!</h3>
</div>
<div class="modal-body">
<p>Why not tweet your selection?</p>
</div>
<div class="modal-footer">
Close
Save changes
</div>
</div>
votes/create.js.erb
$(".modal").html(<%= escape_javascript render partial: 'votes/info' %>);
$(".modal").show();
vote _form.html.erb
<%= form_for([Vote.new(hotel_id: hotel.id)]) do |f| %>
<%= f.hidden_field :hotel_id %>
<%= f.submit "Vote", class: "btn-large btn-info" %>
<% end %>
You didn't show us votes/new.html.erb but I think the problem is that <div class="modal hide fade"> needs to be in that file, not the partial. Also, ensure that the partial file name begins with an underscore, "_info.html.erb".

Categories

Resources