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