web-dev-qa-db-fra.com

Comment afficher Ruby on Rails messages d'erreur de validation de formulaire un par un)

J'essaie de comprendre comment je peux y arriver. Quelqu'un peut-il me conseiller ou me diriger dans la bonne direction?

Cela permet à 1 erreur de chaque champ de s'afficher à la fois. C'est presque ce que je veux faire mais pas tout à fait exactement. Je veux afficher 1 message d'erreur entier à la fois. PAR EXEMPLE. le prénom ne peut pas être vide. Une fois que cela a été résolu, il passe à l'erreur suivante. Donc, si l'utilisateur a ajouté des numéros à son nom de famille, il ne serait plus vierge, mais cela afficherait une autre erreur indiquant que seules les lettres étaient autorisées, etc. correctement leur nom de famille.

<% @user.errors.each do |attr, msg| %>
<%= "#{attr} #{msg}" if @user.errors[attr].first == msg %> 
<% end %>
39
LondonGuy

Après avoir expérimenté pendant quelques heures, je l'ai compris.

<% if @user.errors.full_messages.any? %>
  <% @user.errors.full_messages.each do |error_message| %>
    <%= error_message if @user.errors.full_messages.first == error_message %> <br />
  <% end %>
<% end %>

Encore mieux:

<%= @user.errors.full_messages.first if @user.errors.any? %>
29
LondonGuy

ActiveRecord stocke les erreurs de validation dans un tableau appelé errors. Si vous avez un modèle User, vous accéderez aux erreurs de validation dans une instance donnée comme ceci:

@user = User.create[params[:user]] # create will automatically call validators

if @user.errors.any? # If there are errors, do something

  # You can iterate through all messages by attribute type and validation message
  # This will be something like:
  # attribute = 'name'
  # message = 'cannot be left blank'
  @user.errors.each do |attribute, message|
    # do stuff for each error
  end

  # Or if you prefer, you can get the full message in single string, like so:
  # message = 'Name cannot be left blank'
  @users.errors.full_messages.each do |message|
    # do stuff for each error
  end

  # To get all errors associated with a single attribute, do the following:
  if @user.errors.include?(:name)
    name_errors = @user.errors[:name]

    if name_errors.kind_of?(Array)
      name_errors.each do |error|
        # do stuff for each error on the name attribute
      end
    else
      error = name_errors
      # do stuff for the one error on the name attribute.
    end
  end
end

Bien sûr, vous pouvez également faire tout cela dans les vues au lieu du contrôleur, si vous souhaitez simplement afficher la première erreur à l'utilisateur ou quelque chose.

62
Wade Tandy

Une meilleure idée,

si vous voulez mettre le message d'erreur juste en dessous du champ de texte, vous pouvez faire comme ça

.row.spacer20top
  .col-sm-6.form-group
    = f.label :first_name, "*Your First Name:"
    = f.text_field :first_name, :required => true, class: "form-control"
    = f.error_message_for(:first_name)

Qu'est-ce que error_message_for?
-> Eh bien, c'est un beau hack pour faire des trucs sympas

# Author Shiva Bhusal
# Aug 2016
# in config/initializers/modify_Rails_form_builder.rb
# This will add a new method in the `f` object available in Rails forms
class ActionView::Helpers::FormBuilder
  def error_message_for(field_name)
    if self.object.errors[field_name].present?
      model_name              = self.object.class.name.downcase
      id_of_element           = "error_#{model_name}_#{field_name}"
      target_elem_id          = "#{model_name}_#{field_name}"
      class_name              = 'signup-error alert alert-danger'
      error_declaration_class = 'has-signup-error'

      "<div id=\"#{id_of_element}\" for=\"#{target_elem_id}\" class=\"#{class_name}\">"\
      "#{self.object.errors[field_name].join(', ')}"\
      "</div>"\
      "<!-- Later JavaScript to add class to the parent element -->"\
      "<script>"\
          "document.onreadystatechange = function(){"\
            "$('##{id_of_element}').parent()"\
            ".addClass('#{error_declaration_class}');"\
          "}"\
      "</script>".html_safe
    end
  rescue
    nil
  end
end

Résultat enter image description here

Annotation générée après une erreur

<div id="error_user_email" for="user_email" class="signup-error alert alert-danger">has already been taken</div>
<script>document.onreadystatechange = function(){$('#error_user_email').parent().addClass('has-signup-error');}</script>

SCSS correspondant

  .has-signup-error{
    .signup-error{
      background: transparent;
      color: $brand-danger;
      border: none;
    }

    input, select{
      background-color: $bg-danger;
      border-color: $brand-danger;
      color: $gray-base;
      font-weight: 500;
    }

    &.checkbox{
      label{
        &:before{
          background-color: $bg-danger;
          border-color: $brand-danger;
        }
      }
    }

Remarque: Bootstrap variables utilisées ici

8
illusionist

Je l'ai résolu comme ceci:

<% @user.errors.each do |attr, msg| %>
  <li>
    <%= @user.errors.full_messages_for(attr).first if @user.errors[attr].first == msg %>
  </li>
<% end %>

De cette façon, vous utilisez les paramètres régionaux pour les messages d'erreur.

2
nscherzer