webentwicklung-frage-antwort-db.com.de

So zeigen Sie Ruby on Rails form Validierungsfehlermeldungen nacheinander an

Ich versuche zu verstehen, wie ich das erreichen kann. Kann mich jemand beraten oder in die richtige Richtung weisen?

Dadurch kann jeweils 1 Fehler aus jedem Feld angezeigt werden. Es ist fast das, was ich tun möchte, aber nicht ganz genau. Ich möchte jeweils 1 ganze Fehlermeldung anzeigen. Z.B. Vorname darf nicht leer sein. Sobald dies behoben ist, wird der nächste Fehler behoben. Wenn der Benutzer also Nummern zu seinem Nachnamen hinzufügt, ist dieser nicht mehr leer, sondern es wird ein weiterer Fehler angezeigt, der besagt, dass nur Buchstaben zulässig sind usw. Wenn dieser Fehler behoben wurde, wird der Nachname als Fehler angezeigt oder es wird eine E-Mail gesendet, wenn das Benutzerfeld ausgefüllt ist ihren Nachnamen richtig aus.

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

Nachdem ich ein paar Stunden experimentiert hatte, fand ich es heraus.

<% 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 %>

Noch besser:

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

ActiveRecord speichert Validierungsfehler in einem Array mit dem Namen errors. Wenn Sie ein User Modell haben, würden Sie auf die Validierungsfehler in einer bestimmten Instanz wie folgt zugreifen:

@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

Natürlich können Sie dies auch in den Ansichten anstelle des Controllers tun, wenn Sie dem Benutzer nur den ersten Fehler oder etwas anzeigen möchten.

62
Wade Tandy

Eine bessere Idee,

wenn Sie die Fehlermeldung direkt unter das Textfeld stellen möchten, können Sie dies tun

.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)

Was ist error_message_for?
-> Nun, das ist ein wunderschöner Hack, um ein paar coole Sachen zu machen

# 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

Ergebnis enter image description here

Markup Wird nach einem Fehler generiert

<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>

Entsprechendes SCSS

  .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;
        }
      }
    }

Hinweis: Bootstrap hier verwendete Variablen

8
illusionist

Ich habe es so gelöst:

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

Auf diese Weise verwenden Sie die Ländereinstellungen für die Fehlermeldungen.

2
nscherzer