forms: fix form validation error messages.
* Fix it so that all edit forms show an error banner if the form has validation errors. Previously forms had to manually call `error_messages_for`, which not all forms did. * Fix it so that the full validation error message is shown next to each input attribute that had errors. Also update the styling of these error messages to look better.
This commit is contained in:
@@ -92,16 +92,6 @@ module ApplicationHelper
|
|||||||
DText.strip_dtext(text)
|
DText.strip_dtext(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
def error_messages_for(instance_name)
|
|
||||||
instance = instance_variable_get("@#{instance_name}")
|
|
||||||
|
|
||||||
if instance&.errors&.any?
|
|
||||||
%{<div class="error-messages ui-state-error ui-corner-all"><strong>Error</strong>: #{instance.__send__(:errors).full_messages.join(", ")}</div>}.html_safe
|
|
||||||
else
|
|
||||||
""
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def time_tag(content, time, **options)
|
def time_tag(content, time, **options)
|
||||||
datetime = time.strftime("%Y-%m-%dT%H:%M%:z")
|
datetime = time.strftime("%Y-%m-%dT%H:%M%:z")
|
||||||
|
|
||||||
@@ -256,7 +246,14 @@ module ApplicationHelper
|
|||||||
def edit_form_for(model, **options, &block)
|
def edit_form_for(model, **options, &block)
|
||||||
options[:html] = { autocomplete: "off", **options[:html].to_h }
|
options[:html] = { autocomplete: "off", **options[:html].to_h }
|
||||||
options[:authenticity_token] = true if options[:remote] == true
|
options[:authenticity_token] = true if options[:remote] == true
|
||||||
simple_form_for(model, **options, &block)
|
|
||||||
|
simple_form_for(model, **options) do |form|
|
||||||
|
if model.try(:errors).try(:any?)
|
||||||
|
concat tag.div(model.errors.full_messages.join("; "), class: "notice notice-error notice-small")
|
||||||
|
end
|
||||||
|
|
||||||
|
block.call(form)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def table_for(...)
|
def table_for(...)
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ html {
|
|||||||
--form-input-border-color: var(--grey-2);
|
--form-input-border-color: var(--grey-2);
|
||||||
--form-input-placeholder-text-color: var(--grey-4);
|
--form-input-placeholder-text-color: var(--grey-4);
|
||||||
--form-input-validation-error-border-color: var(--red-4);
|
--form-input-validation-error-border-color: var(--red-4);
|
||||||
|
--form-input-validation-error-text-color: var(--red-5);
|
||||||
|
|
||||||
--form-button-text-color: var(--text-color);
|
--form-button-text-color: var(--text-color);
|
||||||
--form-button-background: var(--grey-1);
|
--form-button-background: var(--grey-1);
|
||||||
@@ -246,8 +247,6 @@ html {
|
|||||||
--keyboard-shortcut-color: var(--inverse-text-color);
|
--keyboard-shortcut-color: var(--inverse-text-color);
|
||||||
--keyboard-shortcut-background-color: var(--grey-6);
|
--keyboard-shortcut-background-color: var(--grey-6);
|
||||||
|
|
||||||
--error-message-color: var(--red-5);
|
|
||||||
|
|
||||||
--login-link-color: var(--red-5);
|
--login-link-color: var(--red-5);
|
||||||
--footer-border-color: var(--grey-1);
|
--footer-border-color: var(--grey-1);
|
||||||
--details-border-color: var(--grey-2);
|
--details-border-color: var(--grey-2);
|
||||||
@@ -326,6 +325,7 @@ body[data-current-user-theme="dark"] {
|
|||||||
--form-input-border-color: var(--grey-5);
|
--form-input-border-color: var(--grey-5);
|
||||||
--form-input-placeholder-text-color: var(--grey-3);
|
--form-input-placeholder-text-color: var(--grey-3);
|
||||||
--form-input-validation-error-border-color: var(--red-4);
|
--form-input-validation-error-border-color: var(--red-4);
|
||||||
|
--form-input-validation-error-text-color: var(--red-5);
|
||||||
|
|
||||||
--form-button-text-color: var(--grey-9);
|
--form-button-text-color: var(--grey-9);
|
||||||
--form-button-background: var(--grey-2);
|
--form-button-background: var(--grey-2);
|
||||||
@@ -444,8 +444,6 @@ body[data-current-user-theme="dark"] {
|
|||||||
--keyboard-shortcut-color: var(--grey-0);
|
--keyboard-shortcut-color: var(--grey-0);
|
||||||
--keyboard-shortcut-background-color: var(--grey-7);
|
--keyboard-shortcut-background-color: var(--grey-7);
|
||||||
|
|
||||||
--error-message-color: var(--red-4);
|
|
||||||
|
|
||||||
--login-link-color: var(--red-4);
|
--login-link-color: var(--red-4);
|
||||||
--footer-border-color: var(--grey-7);
|
--footer-border-color: var(--grey-7);
|
||||||
--details-border-color: var(--grey-7);
|
--details-border-color: var(--grey-7);
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
span.error {
|
|
||||||
display: block;
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--error-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
span.link {
|
span.link {
|
||||||
color: var(--link-color);
|
color: var(--link-color);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@@ -1,13 +1,3 @@
|
|||||||
div.error-messages {
|
|
||||||
margin: 1em 0;
|
|
||||||
padding: 1em;
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 1em;
|
|
||||||
color: var(--error-message-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
div#notice {
|
div#notice {
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|||||||
@@ -44,8 +44,17 @@ form.simple_form {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.field_with_errors input {
|
&.field_with_errors {
|
||||||
border: 1px solid var(--form-input-validation-error-border-color);
|
input, select, textarea {
|
||||||
|
border: 1px solid var(--form-input-validation-error-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
span.error {
|
||||||
|
display: block;
|
||||||
|
color: var(--form-input-validation-error-text-color);
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.text, &.dtext {
|
&.text, &.dtext {
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
<div id="a-new">
|
<div id="a-new">
|
||||||
<h1>New Artist</h1>
|
<h1>New Artist</h1>
|
||||||
|
|
||||||
<%= error_messages_for :artist %>
|
|
||||||
|
|
||||||
<%= render "form" %>
|
<%= render "form" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<%= edit_form_for(ban) do |f| %>
|
<%= edit_form_for(ban) do |f| %>
|
||||||
<%= error_messages_for("ban") %>
|
|
||||||
|
|
||||||
<%= f.input :user_name, :as => :string, :input_html => { data: { autocomplete: "user" } } %>
|
<%= f.input :user_name, :as => :string, :input_html => { data: { autocomplete: "user" } } %>
|
||||||
<%= f.input :duration, :hint => "in days" %>
|
<%= f.input :duration, :hint => "in days" %>
|
||||||
<%= f.input :reason %>
|
<%= f.input :reason %>
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
<h1>Edit Ban</h1>
|
<h1>Edit Ban</h1>
|
||||||
|
|
||||||
<%= edit_form_for(@ban) do |f| %>
|
<%= edit_form_for(@ban) do |f| %>
|
||||||
<%= error_messages_for("ban") %>
|
|
||||||
|
|
||||||
<%= f.input :duration, :hint => "in days" %>
|
<%= f.input :duration, :hint => "in days" %>
|
||||||
<%= f.input :reason %>
|
<%= f.input :reason %>
|
||||||
<%= f.button :submit, :value => "Ban" %>
|
<%= f.button :submit, :value => "Ban" %>
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<%= edit_form_for(@bulk_update_request) do |f| %>
|
<%= edit_form_for(@bulk_update_request) do |f| %>
|
||||||
<%= error_messages_for("bulk_update_request") %>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Request aliases or implications using the format shown below. An <b>alias</b> makes the first tag a
|
Request aliases or implications using the format shown below. An <b>alias</b> makes the first tag a
|
||||||
synonym for the second tag. An <b>implication</b> makes the first tag automatically add the second tag.
|
synonym for the second tag. An <b>implication</b> makes the first tag automatically add the second tag.
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
<%= error_messages_for :comment %>
|
|
||||||
|
|
||||||
<%= edit_form_for(comment, namespace: "post_#{comment&.post_id}_comment_#{comment.id || "new"}", html: { style: ("display: none;" if local_assigns[:hidden]), class: "edit_comment" }) do |f| %>
|
<%= edit_form_for(comment, namespace: "post_#{comment&.post_id}_comment_#{comment.id || "new"}", html: { style: ("display: none;" if local_assigns[:hidden]), class: "edit_comment" }) do |f| %>
|
||||||
<% if comment.new_record? %>
|
<% if comment.new_record? %>
|
||||||
<%= f.hidden_field :post_id %>
|
<%= f.hidden_field :post_id %>
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
<div id="a-edit">
|
<div id="a-edit">
|
||||||
<h1>Edit Favorite Group: <%= @favorite_group.pretty_name %></h1>
|
<h1>Edit Favorite Group: <%= @favorite_group.pretty_name %></h1>
|
||||||
|
|
||||||
<%= error_messages_for "favorite_group" %>
|
|
||||||
|
|
||||||
<%= edit_form_for(@favorite_group) do |f| %>
|
<%= edit_form_for(@favorite_group) do |f| %>
|
||||||
<%= f.input :name, :as => :string, :input_html => { :value => @favorite_group.pretty_name } %>
|
<%= f.input :name, :as => :string, :input_html => { :value => @favorite_group.pretty_name } %>
|
||||||
<%= f.input :post_ids_string, label: "Posts", as: :text %>
|
<%= f.input :post_ids_string, label: "Posts", as: :text %>
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
<div id="a-new">
|
<div id="a-new">
|
||||||
<h1>New Favorite Group</h1>
|
<h1>New Favorite Group</h1>
|
||||||
|
|
||||||
<%= error_messages_for "favorite_group" %>
|
|
||||||
|
|
||||||
<%= edit_form_for(@favorite_group) do |f| %>
|
<%= edit_form_for(@favorite_group) do |f| %>
|
||||||
<%= f.input :name, as: :string, required: true %>
|
<%= f.input :name, as: :string, required: true %>
|
||||||
<%= f.input :post_ids_string, label: "Posts", as: :text %>
|
<%= f.input :post_ids_string, label: "Posts", as: :text %>
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
<%= error_messages_for("forum_post") %>
|
|
||||||
|
|
||||||
<%= edit_form_for(forum_post, namespace: "forum_post_#{forum_post.id}") do |f| %>
|
<%= edit_form_for(forum_post, namespace: "forum_post_#{forum_post.id}") do |f| %>
|
||||||
<%= f.input :body, as: :dtext %>
|
<%= f.input :body, as: :dtext %>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
<%= error_messages_for("forum_post") %>
|
|
||||||
|
|
||||||
<%= edit_form_for(forum_post) do |f| %>
|
<%= edit_form_for(forum_post) do |f| %>
|
||||||
<% if forum_post.topic_id.present? %>
|
<% if forum_post.topic_id.present? %>
|
||||||
<%= f.input :topic_id, :as => :hidden %>
|
<%= f.input :topic_id, :as => :hidden %>
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
<%= error_messages_for("forum_topic") %>
|
|
||||||
|
|
||||||
<div id="form-content">
|
<div id="form-content">
|
||||||
<%= edit_form_for(forum_topic) do |f| %>
|
<%= edit_form_for(forum_topic) do |f| %>
|
||||||
<%= f.input :title %>
|
<%= f.input :title %>
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
they've verified their email address.
|
they've verified their email address.
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
<%= error_messages_for "ip_ban" %>
|
|
||||||
|
|
||||||
<%= edit_form_for(@ip_ban) do |f| %>
|
<%= edit_form_for(@ip_ban) do |f| %>
|
||||||
<%= f.input :ip_addr, label: "IP Address", as: :string, hint: "Add /24 to ban a subnet. Example: 1.2.3.4/24" %>
|
<%= f.input :ip_addr, label: "IP Address", as: :string, hint: "Add /24 to ban a subnet. Example: 1.2.3.4/24" %>
|
||||||
<%= f.input :reason, as: :string %>
|
<%= f.input :reason, as: :string %>
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
<%= edit_form_for(@pool) do |f| %>
|
<%= edit_form_for(@pool) do |f| %>
|
||||||
<h1>Edit Pool: <%= @pool.pretty_name %></h1>
|
<h1>Edit Pool: <%= @pool.pretty_name %></h1>
|
||||||
|
|
||||||
<%= error_messages_for "pool" %>
|
|
||||||
|
|
||||||
<%= f.input :name, :as => :string, :input_html => { :value => @pool.pretty_name } %>
|
<%= f.input :name, :as => :string, :input_html => { :value => @pool.pretty_name } %>
|
||||||
<%= f.input :description, as: :dtext %>
|
<%= f.input :description, as: :dtext %>
|
||||||
<%= f.input :post_ids_string, as: :text, label: "Posts" %>
|
<%= f.input :post_ids_string, as: :text, label: "Posts" %>
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
<div id="a-edit">
|
<div id="a-edit">
|
||||||
<h1>Edit Saved Search</h1>
|
<h1>Edit Saved Search</h1>
|
||||||
|
|
||||||
<%= error_messages_for :saved_search %>
|
|
||||||
|
|
||||||
<%= edit_form_for(@saved_search) do |f| %>
|
<%= edit_form_for(@saved_search) do |f| %>
|
||||||
<%= f.input :query, :as => :string %>
|
<%= f.input :query, :as => :string %>
|
||||||
<%= f.input :label_string, label: "Labels", hint: "A list of tags to help categorize this search. Space delimited.", input_html: { "data-autocomplete": "saved-search-label" } %>
|
<%= f.input :label_string, label: "Labels", hint: "A list of tags to help categorize this search. Space delimited.", input_html: { "data-autocomplete": "saved-search-label" } %>
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
<div id="preview">
|
<div id="preview">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= error_messages_for "user_feedback" %>
|
|
||||||
|
|
||||||
<%= edit_form_for(@user_feedback) do |f| %>
|
<%= edit_form_for(@user_feedback) do |f| %>
|
||||||
<%= f.input :category, :collection => ["positive", "neutral", "negative"], :include_blank => false %>
|
<%= f.input :category, :collection => ["positive", "neutral", "negative"], :include_blank => false %>
|
||||||
<%= f.input :body, as: :dtext %>
|
<%= f.input :body, as: :dtext %>
|
||||||
|
|||||||
@@ -11,8 +11,6 @@
|
|||||||
<div id="preview">
|
<div id="preview">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= error_messages_for "user_feedback" %>
|
|
||||||
|
|
||||||
<%= edit_form_for(@user_feedback) do |f| %>
|
<%= edit_form_for(@user_feedback) do |f| %>
|
||||||
<%= f.input :user_name, :label => "User", :input_html => { value: @user_feedback.user.try(:name), data: { autocomplete: "user" } } %>
|
<%= f.input :user_name, :label => "User", :input_html => { value: @user_feedback.user.try(:name), data: { autocomplete: "user" } } %>
|
||||||
<%= f.input :category, :collection => ["positive", "neutral", "negative"], :include_blank => false %>
|
<%= f.input :category, :collection => ["positive", "neutral", "negative"], :include_blank => false %>
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
be visible on your profile to other Danbooru members, but they won't be visible
|
be visible on your profile to other Danbooru members, but they won't be visible
|
||||||
to search engines.</p>
|
to search engines.</p>
|
||||||
|
|
||||||
<%= error_messages_for "change_request" %>
|
|
||||||
|
|
||||||
<%= edit_form_for(@change_request) do |f| %>
|
<%= edit_form_for(@change_request) do |f| %>
|
||||||
<%= f.input :desired_name, label: "Name" %>
|
<%= f.input :desired_name, label: "Name" %>
|
||||||
<%= f.input :desired_name_confirmation, label: "Confirm name" %>
|
<%= f.input :desired_name_confirmation, label: "Confirm name" %>
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<div id="form-content">
|
<div id="form-content">
|
||||||
<%= error_messages_for("wiki_page") %>
|
|
||||||
|
|
||||||
<%= edit_form_for(@wiki_page, url: wiki_page_path(@wiki_page.id)) do |f| %>
|
<%= edit_form_for(@wiki_page, url: wiki_page_path(@wiki_page.id)) do |f| %>
|
||||||
<%= f.input :title, error: false, input_html: { data: { autocomplete: "tag" } }, hint: "Change to rename this wiki page. Update any wikis linking to this page first." %>
|
<%= f.input :title, error: false, input_html: { data: { autocomplete: "tag" } }, hint: "Change to rename this wiki page. Update any wikis linking to this page first." %>
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= error_messages_for("wiki_page") %>
|
|
||||||
|
|
||||||
<%= edit_form_for(@wiki_page) do |f| %>
|
<%= edit_form_for(@wiki_page) do |f| %>
|
||||||
<%= f.input :title, error: false, input_html: { data: { autocomplete: "tag" } } %>
|
<%= f.input :title, error: false, input_html: { data: { autocomplete: "tag" } } %>
|
||||||
<%= f.input :other_names_string, as: :string, label: "Other names (#{link_to_wiki "help", "help:translated_tags"})".html_safe, hint: "Names used for this tag on other sites such as Pixiv. Separate with spaces." %>
|
<%= f.input :other_names_string, as: :string, label: "Other names (#{link_to_wiki "help", "help:translated_tags"})".html_safe, hint: "Names used for this tag on other sites such as Pixiv. Separate with spaces." %>
|
||||||
|
|||||||
@@ -57,13 +57,13 @@ SimpleForm.setup do |config|
|
|||||||
# b.use :input, class: 'input', error_class: 'is-invalid', valid_class: 'is-valid'
|
# b.use :input, class: 'input', error_class: 'is-invalid', valid_class: 'is-valid'
|
||||||
b.use :label_input
|
b.use :label_input
|
||||||
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
||||||
b.use :error, wrap_with: { tag: :span, class: :error }
|
# b.use :error, wrap_with: { tag: :span, class: :error }
|
||||||
|
|
||||||
## full_messages_for
|
## full_messages_for
|
||||||
# If you want to display the full error message for the attribute, you can
|
# If you want to display the full error message for the attribute, you can
|
||||||
# use the component :full_error, like:
|
# use the component :full_error, like:
|
||||||
#
|
#
|
||||||
# b.use :full_error, wrap_with: { tag: :span, class: :error }
|
b.use :full_error, wrap_with: { tag: :span, class: :error }
|
||||||
end
|
end
|
||||||
|
|
||||||
# The default wrapper to be used by the FormBuilder.
|
# The default wrapper to be used by the FormBuilder.
|
||||||
@@ -87,7 +87,7 @@ SimpleForm.setup do |config|
|
|||||||
# Method used to tidy up errors. Specify any Rails Array method.
|
# Method used to tidy up errors. Specify any Rails Array method.
|
||||||
# :first lists the first message for each field.
|
# :first lists the first message for each field.
|
||||||
# Use :to_sentence to list all errors for each field.
|
# Use :to_sentence to list all errors for each field.
|
||||||
# config.error_method = :first
|
config.error_method = :to_sentence
|
||||||
|
|
||||||
# Default tag used for error notification helper.
|
# Default tag used for error notification helper.
|
||||||
config.error_notification_tag = :div
|
config.error_notification_tag = :div
|
||||||
|
|||||||
Reference in New Issue
Block a user