Rails 3: el contenedor “campo con errores” cambia el aspecto de la página. ¿Cómo evitar esto?

Campo de correo electrónico:

  

Se ve como esto:

sin error

Pero, si la validación del correo electrónico falla, se convierte en:

 

que se ve así:

with_error

¿Cómo podría evitar este cambio de apariencia?

Debería anular ActionView::Base.field_error_proc . Actualmente se define como esto en ActionView::Base :

  @@field_error_proc = Proc.new{ |html_tag, instance| "
#{html_tag}
".html_safe }

Puede anularlo poniendo esto en la clase de su aplicación dentro de config/application.rb :

 config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag } 

Reinicie el servidor de Rails para que este cambio surta efecto.

La diferencia visual que está viendo está sucediendo porque el elemento div es un elemento de bloque. Agregue este estilo a su archivo CSS para que se comporte como un elemento en línea:

 .field_with_errors { display: inline; } 

Actualmente uso esta solución, colocada en un inicializador:

 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 

Esto me permite simplemente agregar un nombre de clase a la etiqueta apropiada, sin crear elementos adicionales.

El código adicional está siendo agregado por ActionView::Base.field_error_proc . Si no está utilizando field_with_errors para field_with_errors estilo a su formulario, puede anularlo en application.rb :

 config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag.html_safe } 

Alternativamente, puede cambiarlo a algo que se adapte a su UI:

 config.action_view.field_error_proc = Proc.new { |html_tag, instance| "#{html_tag}".html_safe } 

Además de @phobetron answer, que no funciona cuando tienes otra etiqueta con atributo de clase, como .

Hice algunos cambios en su solución:

 # 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 

Estoy trabajando con Rails 5 y Materialise-Sass y estoy recibiendo algunos problemas con el comportamiento predeterminado de Rails para tratar validaciones de campo fallidas como en la imagen de abajo y fue debido a la div adicional agregada a los campos de entrada donde falló la validación.

enter image description here

Trabajar con @Phobetron responde y modifica la respuesta de Hugo Demiglio también. Hice algunos ajustes a esos bloques de código y obtengo algo que funciona bien en los siguientes casos:

  • Si tanto la input como la label tienen su propio atributo de class cualquier lugar
  • Si las label input o tags no tienen un atributo de class
  • si la etiqueta tiene otra etiqueta adentro con el class attribute

En todos esos casos, la clase de error se agregará a las clases existentes en el atributo de class si existe o se creará si no está presente en la etiqueta o tags de entrada .

 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 

Espero que pueda ser útil para alguien con las mismas condiciones que yo.

Si por alguna razón todavía trabajas en Rails 2 (como yo), echa un vistazo a la publicación SO aquí .

Ofrece una secuencia de comandos para poner en inicializadores.

Una cosa que hay que tener en cuenta (como descubrí trabajando en esto hoy) es que si flotas la etiqueta o los campos de entrada (estoy flotando todos los campos de entrada a la derecha), el css se romperá incluso si anulas ActionView :: Base.field_error_proc.

Una alternativa es bajar un nivel más profundo en el formato CSS de esta manera:

 .field_with_errors label { padding: 2px; background-color: red; } .field_with_errors input[type="text"] { padding: 3px 2px; border: 2px solid red; } 

Hice una opción para desactivar esta cosa terrible para algunos objetos

 # 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 "
#{html_tag}
".html_safe end }

Entonces puede usarlo así:

 @user.skip_field_error_wrapper = true form_for(@user) do |f| ... end 

Esta es mi solución basada en la respuesta de @ Phobetron. Al colocar este código en application.rb , sus tags

y generadas por las llamadas form.error :p correspondientes recibirán la etiqueta fields_with_errors css. El rest recibirá la clase CSS de error .

 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 } 

De esta forma encontré el más flexible y discreto de todos los anteriores a la respuesta del estilo en mis formularios.

Si es solo por motivos de estilo (no le importa el div ), puede agregar esto a su CSS:

 div.field_with_errors { display: inline; } 

El div actuará como un span y no interferirá con su diseño (ya que div es un elemento de bloque – display: block; – de forma predeterminada, causará una nueva línea después de que se cierre; span está en inline , por lo que no )

Si solo se trata de problemas de diseño, podemos sobreescribir “field_with_errors”. Pero como eso podría afectar a otros formularios en nuestra aplicación, es mejor sobrescribir la clase “field_with_errors” con ese formulario solamente.

Teniendo en cuenta ‘parent_class’ es una de las clases padre para el campo de error del formulario (ya sea la clase del formulario o la clase de cualquiera del elemento padre para el campo de error), luego

  .parent_class .field_with_errors { display: inline; } 

Solucionará el problema y no alterará ninguna otra forma en nuestra aplicación.

O

Si necesitamos anular el estilo de “campo_con_errores” para toda la aplicación, entonces como dijo @dontangg,

 .field_with_errors { display: inline; } 

hará la corrección. Espero eso ayude 🙂