Courriel:
<label for="job_client_email">Email: </label>
<input type="email" name="job[client_email]" id="job_client_email">
ressemble à ça:
Mais si la validation de l'e-mail échoue, cela devient:
<div class="field_with_errors">
<label for="job_client_email">Email: </label>
</div>
<div class="field_with_errors">
<input type="email" value="wrong email" name="job[client_email]" id="job_client_email">
</div>
qui ressemble à ceci:
Comment pourrais-je éviter ce changement d'aspect?
Vous devriez remplacer ActionView::Base.field_error_proc
. Il est actuellement défini comme ceci dans ActionView::Base
:
@@field_error_proc = Proc.new{ |html_tag, instance|
"<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
}
Vous pouvez le remplacer en le mettant dans la classe de votre application à l'intérieur de config/application.rb
:
config.action_view.field_error_proc = Proc.new { |html_tag, instance|
html_tag
}
Redémarrez le serveur Rails pour que cette modification soit prise en compte).
La différence visuelle que vous voyez se produit parce que l'élément div
est un élément de bloc. Ajoutez ce style à votre fichier CSS pour le faire se comporter comme un élément en ligne:
.field_with_errors { display: inline; }
J'utilise actuellement cette solution, placée dans un initialiseur:
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
class_attr_index = html_tag.index 'class="'
if class_attr_index
html_tag.insert class_attr_index+7, 'error '
else
html_tag.insert html_tag.index('>'), ' class="error"'
end
end
Cela me permet simplement d'ajouter un nom de classe à la balise appropriée, sans créer d'éléments supplémentaires.
Le code supplémentaire est ajouté par ActionView::Base.field_error_proc
. Si vous n'utilisez pas field_with_errors
pour styler votre formulaire, vous pouvez le remplacer dans application.rb
:
config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag.html_safe }
Alternativement, vous pouvez le changer pour quelque chose qui convient à votre interface utilisateur:
config.action_view.field_error_proc = Proc.new { |html_tag, instance| "<span class='field_with_errors'>#{html_tag}</span>".html_safe }
Je travaille avec Rails 5 et Materialise-Sass et j'ai quelques problèmes avec le comportement par défaut de Rails pour traiter échoué les validations de champs comme dans l’image ci-dessous et c’est à cause du supplément de div
ajouté aux champs de saisie où la validation a échoué.
Travailler avec @Phobetron répond et modifie également la réponse de Hugo Demiglio. J'ai apporté quelques ajustements à ces blocs de code et quelque chose fonctionne bien dans les cas suivants:
input
et label
ont chacun leur propre attribut class
n'importe où <input type="my-field" class="control">
<label class="active" for="...">My field</label>
input
ou label
n'ont pas d'attribut class
<input type="my-field">
<label for="...">My field</label>
label
a une autre balise à l'intérieur avec le class attribute
<label for="..."><i class="icon-name"></i>My field</label>
Dans tous ces cas, la classe error
sera ajoutée aux classes existantes dans l'attribut class
s'il existe ou elle sera créée si elle n'est pas présente dans le label ou saisissez des balises .
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
class_attr_index = html_tag.index('class="')
first_tag_end_index = html_tag.index('>')
# Just to inspect variables in the console
puts '???? ' * 50
pp(html_tag)
pp(class_attr_index)
pp(first_tag_end_index)
if class_attr_index.nil? || class_attr_index > first_tag_end_index
html_tag.insert(first_tag_end_index, ' class="error"')
else
html_tag.insert(class_attr_index + 7, 'error ')
end
# Just to see resulting tag in the console
pp(html_tag)
end
J'espère que cela pourrait être utile pour quelqu'un qui a les mêmes conditions que moi.
En plus de @phobetron answer, ce qui ne fonctionne pas si vous avez une autre balise avec un attribut class, comme <label for="..."><i class="icon my-icon"></i>My field</label>
.
J'ai fait quelques changements sur sa solution:
# config/initializers/field_with_error.rb
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
class_attr_index = html_tag.index('class="')
first_tag_end_index = html_tag.index('>')
if class_attr_index.nil? || first_tag_end_index > class_attr_index
html_tag.insert(class_attr_index + 7, 'error ')
else
html_tag.insert(first_tag_end_index, ' class="error"')
end
end
J'ai fait une option pour désactiver cette chose terrible pour certains objets
# config/initializers/field_error_proc.rb
module ActiveModel::Conversion
attr_accessor :skip_field_error_wrapper
end
ActionView::Base.field_error_proc = Proc.new {|html_tag, instance|
if instance.object && instance.object.skip_field_error_wrapper
html_tag.html_safe
else
"<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
end
}
Alors peut l'utiliser comme ça:
@user.skip_field_error_wrapper = true
form_for(@user) do |f|
...
end
Si pour une raison quelconque vous travaillez toujours sur Rails 2 (comme je le suis), consultez le SO post ici .
Il propose un script à mettre dans les initialiseurs.
Une chose à garder à l’esprit (comme je l’ai découvert aujourd’hui) est que, si vous flottez l’étiquette ou les champs d’entrée (je flotte tous les champs d’entrée à droite), le css se cassera même si vous écrasez ActionView :: Base.field_error_proc.
Une alternative consiste à abandonner un niveau plus profond dans la mise en forme CSS comme ceci:
.field_with_errors label {
padding: 2px;
background-color: red;
}
.field_with_errors input[type="text"] {
padding: 3px 2px;
border: 2px solid red;
}
Si c'est uniquement à des fins de style (vous ne vous occupez pas de div
), vous pouvez simplement ajouter ceci à votre css:
div.field_with_errors {
display: inline;
}
Le div
agira comme un span
et n'interférera pas avec votre conception (puisque div
est un élément de bloc - display: block;
_ Par défaut, une nouvelle ligne sera créée après sa fermeture. span
est inline
, donc ce n'est pas le cas).
C’est ma solution qui s’appuie sur la réponse de @ Phobetron. Placer ce code dans application.rb
, votre <p>
et <span>
tags générés par le form.error :p
les appels recevront le fields_with_errors
balise css. Le reste recevra la classe CSS error
CSS.
config.action_view.field_error_proc = Proc.new { |html_tag, instance|
class_attr_index = html_tag.index 'class="'
if class_attr_index
# target only p's and span's with class error already there
error_class = if html_tag =~ /^<(p|span).*error/
'field_with_errors '
else
'error '
end
html_tag.insert class_attr_index + 7, error_class
else
html_tag.insert html_tag.index('>'), ' class="error"'
end
}
Je trouvais ainsi le moyen le plus flexible et le plus discret de tous les précédents de styliser la réponse dans mes formulaires.
S'il ne s'agit que de problèmes de style, nous pouvons écraser "field_with_errors". Mais comme cela pourrait affecter d'autres formulaires dans notre application, il est préférable d'écraser la classe "field_with_errors" dans ce formulaire uniquement.
Considérant que 'parent_class' est l'une des classes parentes du champ d'erreur du formulaire (la classe du formulaire ou la classe de l'un des éléments parents du champ d'erreur), puis
.parent_class .field_with_errors {
display: inline;
}
Cela résoudra le problème aussi bien que, cela ne perturbera pas d'autres formes dans notre application.
OR
Si nous devons remplacer le style de "field_with_errors" pour toute une application, alors comme @dontangg l'a dit,
.field_with_errors { display: inline; }
fera le correctif. J'espère que ça aide :)
Si vous souhaitez simplement désactiver les erreurs pour certains éléments, par exemple cases à cocher, vous pouvez le faire:
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
doc = Nokogiri::HTML::Document.parse(html_tag)
if doc.xpath("//*[@type='checkbox']").any?
html_tag
else
"<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
end
end