Adding error_notification helper to show a default message at the top of forms when object has errors

This commit is contained in:
Carlos Antonio da Silva 2010-07-06 17:29:26 -03:00
parent e534bd2f4f
commit b779fe0ab9
9 changed files with 148 additions and 7 deletions

View File

@ -1,4 +1,5 @@
* enhancements
* Added error_notification message to form builder
* Added required by default as configuration option
* Added label_input as component, allowing boolean to change its order (input appearing first than label)
* Added error_method to tidy up how errors are exhibited

View File

@ -8,3 +8,17 @@ en:
# You can uncomment the line below if you need to overwrite the whole required html.
# When using html, text and mark won't be used.
# html: '<abbr title="required">*</abbr>'
error_notification:
default_message: "Some errors were found, please take a look:"
# Labels and hints examples
# labels:
# password: 'Password'
# user:
# new:
# email: 'E-mail para efetuar o sign in.'
# edit:
# email: 'E-mail.'
# hints:
# username: 'User name to sign in.'
# password: 'No special characters, please.'

View File

@ -14,6 +14,9 @@ SimpleForm.setup do |config|
# Method used to tidy up errors.
# config.error_method = :first
# Default tag used for error notification helper.
# config.error_notification_tag = :p
# You can wrap all inputs in a pre-defined tag.
# config.wrapper_tag = :div

View File

@ -3,11 +3,12 @@ require 'simple_form/action_view_extensions/form_helper'
require 'simple_form/action_view_extensions/builder'
module SimpleForm
autoload :Components, 'simple_form/components'
autoload :FormBuilder, 'simple_form/form_builder'
autoload :I18nCache, 'simple_form/i18n_cache'
autoload :Inputs, 'simple_form/inputs'
autoload :MapType, 'simple_form/map_type'
autoload :Components, 'simple_form/components'
autoload :ErrorNotification, 'simple_form/error_notification'
autoload :FormBuilder, 'simple_form/form_builder'
autoload :I18nCache, 'simple_form/i18n_cache'
autoload :Inputs, 'simple_form/inputs'
autoload :MapType, 'simple_form/map_type'
# Default tag used on hints.
mattr_accessor :hint_tag
@ -21,6 +22,10 @@ module SimpleForm
mattr_accessor :error_method
@@error_method = :first
# Default tag used for error notification helper.
mattr_accessor :error_notification_tag
@@error_notification_tag = :p
# Components used by the form builder.
mattr_accessor :components
@@components = [ :label_input, :hint, :error ]

View File

@ -2,7 +2,7 @@ module SimpleForm
module Components
module Errors
def error
template.content_tag(error_tag, error_text, error_html_options) if object && errors.present?
template.content_tag(error_tag, error_text, error_html_options) if has_errors?
end
def error_tag
@ -23,6 +23,10 @@ module SimpleForm
protected
def has_errors?
object && errors.present?
end
def errors
@errors ||= (errors_on_attribute + errors_on_association).compact
end

View File

@ -23,7 +23,7 @@ module SimpleForm
def wrapper_html_options
css_classes = input_html_classes.unshift(wrapper_class)
css_classes << wrapper_error_class if object && errors.present?
css_classes << wrapper_error_class if has_errors?
html_options_for(:wrapper, css_classes)
end
end

View File

@ -0,0 +1,36 @@
module SimpleForm
class ErrorNotification
delegate :object, :object_name, :template, :to => :@builder
def initialize(builder, options)
@builder = builder
@options = options
end
def render
if has_errors?
error_message = @options.delete(:message) || translate_error_notification
@options[:class] = "error_notification #{@options[:class]}".strip
template.content_tag(error_notification_tag, error_message, @options)
end
end
protected
def error_notification_tag
SimpleForm.error_notification_tag
end
def has_errors?
object && object.respond_to?(:errors) && object.errors.present?
end
def translate_error_notification
lookups = []
lookups << :"#{object_name}"
lookups << :default_message
lookups << "Some errors were found, please take a look:"
I18n.t(lookups.shift, :scope => :"simple_form.error_notification", :default => lookups)
end
end
end

View File

@ -216,6 +216,21 @@ module SimpleForm
SimpleForm::Inputs::Base.new(self).label
end
# Creates an error notification message that only appears when the form object
# has some error. You can give a specific message with the :message option,
# otherwise it will look for a message using I18n. All other options given are
# passed straight as html options to the html tag.
#
# == Examples
#
# f.error_notification
# f.error_notification :message => 'Something went wrong'
# f.error_notification :id => 'user_error_message', :class => 'form_error'
#
def error_notification(options={})
SimpleForm::ErrorNotification.new(self, options).render
end
private
# Setup default simple form attributes.

View File

@ -0,0 +1,63 @@
require 'test_helper'
class ErrorNotificationTest < ActionView::TestCase
def with_error_notification_for(object, options={}, &block)
concat(simple_form_for(object) do |f|
concat(f.error_notification(options))
end)
end
test 'error notification is not generated when the form has no error' do
valid_user = ValidatingUser.new
valid_user.name = 'Carlos'
assert valid_user.valid?
with_error_notification_for valid_user
assert_no_select 'p.error_notification'
end
test 'error notification is not generated for forms without objects' do
with_error_notification_for :user
assert_no_select 'p.error_notification'
end
test 'error notification is generated when the form has some error' do
with_error_notification_for @user
assert_select 'p.error_notification', 'Some errors were found, please take a look:'
end
test 'error notification uses I18n based on model to generate the notification message' do
store_translations(:en, :simple_form => { :error_notification => { :user =>
'Alguns erros foram encontrados para o usuário:'
} }) do
with_error_notification_for @user
assert_select 'p.error_notification', 'Alguns erros foram encontrados para o usuário:'
end
end
test 'error notification uses I18n fallbacking to default message' do
store_translations(:en, :simple_form => { :error_notification => {
:default_message => 'Opa! Alguns erros foram encontrados, poderia verificar?'
} }) do
with_error_notification_for @user
assert_select 'p.error_notification', 'Opa! Alguns erros foram encontrados, poderia verificar?'
end
end
test 'error notification allows passing the notification message' do
with_error_notification_for @user, :message => 'Erro encontrado ao criar usuario'
assert_select 'p.error_notification', 'Erro encontrado ao criar usuario'
end
test 'error notification accepts other html options' do
with_error_notification_for @user, :id => 'user_error_message', :class => 'form_error'
assert_select 'p#user_error_message.form_error.error_notification'
end
test 'error notification allows configuring the wrapper element' do
swap SimpleForm, :error_notification_tag => :div do
with_error_notification_for @user
assert_select 'div.error_notification'
end
end
end