I want to flash a notice/error if the email is/isn't saved, without using a redirect. I am using Rails 4 for the project, and here is my code:
layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>FarFlung Jobs</title>
<!-- /.You can include style.css into stylesheet_link_tag too. If you do so, dont forget to add style.css in asset.rb -->
<%= stylesheet_link_tag 'application', 'jobs', media: 'all' %>
<%= javascript_include_tag 'application' %>
<%= javascript_include_tag 'config', 'sharebutton', 'jobsalert', 'modernizr'%>
<%= render 'payola/transactions/stripe_header' %>
<%= csrf_meta_tags %>
</head>
<body>
<%= render 'shared/navbar' %>
<div>
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, class: 'alert alert-info' %>
<% end %>
</div>
<%= yield %>
<%= render 'shared/footer' %>
</body>
</html>
users/new.html.erb
<section class="cd-form-wrapper cd-container">
<div class="column panel panel-default">
<div class="cd-filter"><h4>SUBSCRIBE FOR JOBS ALERT</h4></div>
<%= simple_form_for User.new do |f| %>
<%= f.input :email, label: false, :placeholder => 'Enter your email address...', :input_html => { :class => 'newsletter-form-field-styling' } %>
<%= f.button :submit, 'SUBMIT', :class => 'btn-block newsletter-form-styling btn-primary submit' %>
<% end %>
</div>
</section>
users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(secure_params)
if @user.valid?
@user.save
flash.now[:notice] = "#{@user.email} is signed up for Jobs Alert."
else
flash.now[:alert] = 'Error Subscribing!'
end
end
private
def secure_params
params.require(:user).permit(:email)
end
end
How do I get the Rails flash message working to appear on my subscription form without redirecting the page?
You can submit your form passing remote: true
. It'll (as you can expect) remotely submit your form, so you can return an json an render the expected flash. Ex:
Your form:
simple_form_for User.new, remote: true, class: 'your-form' do
<your code>
Your controller
def create
@user = User.new(secure_params)
if @user.save
render json: { status: 'success', message: "#{@user.email} is signed up for Jobs Alert." }
else
render json: { status: 'failure', message: 'Error Subscribing!' }
end
end
Your JS (perhaps new.js - and be sure to include it in your view)
// you can specify your bind container, here I just used the document
$(document).on('ajax:success', '.your-form', function(e, data) {
if(data.status == 'success'){
showSuccessFlash(data);
}else{
showErrorFlash(data);
}
});
Explaining:
Using the remote: true
, your page will wait for an ajax answer, which you can get listening to ajax:success
(or other bindings).
Then, it will receive the json
and will store in the data
variable. So you will get the data.status
and the data.message
, which you can show to your user as a feedback.
More infor about the remote: true
http://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#form-for
More info about the JS callbacks https://github.com/rails/jquery-ujs/wiki/ajax
You can use a gem like Gon that will monitor variables and handle all of the Ajax for you automatically.
It's very easy to setup, and you can have it perform the update at whatever time interval you choose. If you're simply transporting a variable, this will save you some Ajax coding. And it will update your page without any kind of redirect, so it does exactly what you're looking for.
However, one other tweak I figured out to solve this problem is with/without redirect is using application helper
to make your Flash Global and used on any View of your choice.
Move your Flash Message to Partials e.g.
shared/_flash_messages.html.erb
<div class="text-center">
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, class: 'alert alert-info' %>
<% end %>
</div>
Define custom helper method for your flash messages using the exact same old rails method use to have. Such that the method renders our partials and the object will be parsed along to your partials.
helpers/application_helper.rb
module ApplicationHelper
def flash_messages_for(object)
render(:partial => 'shared/flash_messages', :locals => {:object => object})
end
end
Inside my View, you can call it with erb tags and call the form object on it such as <%= flash_messages_for(User.new) %>
or <%= flash_messages_for(@user) %>
. See code below:
users/new.html.erb
<section class="cd-form-wrapper cd-container">
<div class="column panel panel-default">
<%= flash_messages_for(User.new) %>
<div class="cd-filter"><h4>SUBSCRIBE FOR JOBS ALERT</h4></div>
<%= simple_form_for(User.new) do |f| %>
<%= f.input :email, label: false, :placeholder => 'Enter your email address...', :input_html => { :class => 'newsletter-form-field-styling' } %>
<%= f.button :submit, 'SUBMIT', :class => 'btn-block newsletter-form-styling btn-primary submit' %>
<% end %>
</div>
With this, my error messages are flashed on any view or form I call <%= flash_messages_for(User.new) %>
on.
You can refer to Kevin Skoglund formerrors
Ruby on Rails Tutorials on Lynda.com Click to watch