Rails 3: el envoltorio "campo con errores" cambia el aspecto de la página. Cómo evitar esto?
Campo de correo electrónico:
<label for="job_client_email">Email: </label>
<input type="email" name="job[client_email]" id="job_client_email">
Se ve así:
Pero, si la validación de correo electrónico falla, se convierte en:
<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>
Que se ve así:
¿Cómo podría evitar este cambio de apariencia ?
12 answers
Debe anular ActionView::Base.field_error_proc
. Actualmente se define como esto dentro de ActionView::Base
:
@@field_error_proc = Proc.new{ |html_tag, instance|
"<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
}
Puedes anularlo poniendo esto en la clase de tu aplicación dentro de config/application.rb
:
config.action_view.field_error_proc = Proc.new { |html_tag, instance|
html_tag
}
Reinicie el servidor rails para que este cambio surta efecto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-06 00:46:46
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; }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-11 01:38:35
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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-05 02:29:20
El código extra está siendo añadido por ActionView::Base.field_error_proc
. Si no estás usando field_with_errors
para darle estilo a tu formulario, puedes anularlo en application.rb
:
config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag.html_safe }
Alternativamente, puedes cambiarlo a algo que se adapte a tu IU:
config.action_view.field_error_proc = Proc.new { |html_tag, instance| "<span class='field_with_errors'>#{html_tag}</span>".html_safe }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-11 01:46:24
Además de @phobetron answer, que no funciona cuando tienes otra etiqueta con atributo de clase, como <label for="..."><i class="icon my-icon"></i>My field</label>
.
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-28 20:02:11
Estoy trabajando con Rails 5 y Materialize-Sass y estoy teniendo algunos problemas con el comportamiento predeterminado de Rails para tratar las validaciones de campos fallidas como en la imagen de abajo y fue debido al extra div
agregado a los campos de entrada donde la validación falló.
Trabajando con la respuesta de @Phobetron y modificando también la respuesta de Hugo Demiglio. Hice algunos ajustes a esos bloques de código y tengo algo que funciona bien en lo siguiente casos:
- Si tanto
input
comolabel
tienen su propio atributoclass
en cualquier lugar<input type="my-field" class="control">
<label class="active" for="...">My field</label>
- Si las etiquetas
input
olabel
no tienen un atributoclass
<input type="my-field">
<label for="...">My field</label>
- si la etiqueta
label
tiene otra etiqueta dentro con la etiquetaclass attribute
<label for="..."><i class="icon-name"></i>My field</label>
En todos esos casos, la clase error
se agregará a las clases existentes en el atributo class
si existen o se creará si no está presente en las etiquetas label o input.
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 como yo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-31 03:59:05
Si por alguna razón sigues trabajando en Rails 2 (como yo) echa un vistazo al post SO aquí.
Ofrece un script para poner en inicializadores.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:32:29
Una cosa a tener en cuenta (como descubrí trabajando con esto hoy) es que si flotan ya sea la etiqueta o los campos de entrada (estoy flotando todos los campos de entrada a la derecha), el css romperá incluso si se sobrescribe ActionView::Base.field_error_proc.
Una alternativa es bajar un nivel más profundo en el formato CSS de la siguiente manera:
.field_with_errors label {
padding: 2px;
background-color: red;
}
.field_with_errors input[type="text"] {
padding: 3px 2px;
border: 2px solid red;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-06 19:53:23
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
"<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
end
}
Así que puede usarlo de esta manera:
@user.skip_field_error_wrapper = true
form_for(@user) do |f|
...
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-15 06:29:33
Esta es mi solución basada en la respuesta de @Phobetron. Al colocar este código en application.rb
, sus etiquetas <p>
y <span>
generadas por las llamadas form.error :p
correspondientes recibirán la etiqueta css fields_with_errors
. El resto recibirá la clase CSS 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
}
Encontré de esta manera la más flexible y discreta de todas las anteriores para estilizar la respuesta a través de mis formularios.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-11 13:51:18
Si es solo para propósitos de estilo (no te importa el div
), puedes agregar esto a tu 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;
– por defecto, causará una nueva línea después de que se cierre; span
es inline
, por lo que no lo hace).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-28 14:44:13
Si solo se trata de problemas de estilo, podemos sobrescribir "field_with_errors". Pero como eso podría afectar a otras formas en nuestra aplicación, es mejor sobrescribir la clase "field_with_errors" con solo en esa forma.
Considerando '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 de los elementos padre para el campo de error), entonces
.parent_class .field_with_errors {
display: inline;
}
Solucionará el problema, así como, no perturbará ninguna otra forma en nuestra aplicación como bien.
O
Si necesitamos anular el estilo de "field_with_errors" para toda la aplicación, entonces como dijo @dontangg,
.field_with_errors { display: inline; }
Hará la corrección. Espero que ayude :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-21 12:00:30