validator validations validate rails method custom create ruby-on-rails ruby-on-rails-3 validation field-with-errors

ruby-on-rails - validations - rails validate scope



Rails 3: el contenedor "campo con errores" cambia el aspecto de la página. ¿Cómo evitar esto? (12)

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 como esto:

Pero, si la validación del 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?


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.


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


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

@@field_error_proc = Proc.new{ |html_tag, instance| "<div class=/"field_with_errors/">#{html_tag}</div>".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 rieles para que este cambio surta efecto.


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| "<span class=''field_with_errors''>#{html_tag}</span>".html_safe }


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 fields_with_errors css. El resto 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.


Estoy trabajando con Rails 5 y Materialize-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.

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
    • <input type="my-field" class="control">
    • <label class="active" for="...">My field</label>
  • Si las label input o etiquetas no tienen un atributo de class
    • <input type="my-field">
    • <label for="...">My field</label>
  • si la etiqueta tiene otra etiqueta adentro con el class attribute
    • <label for="..."><i class="icon-name"></i>My field</label>

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


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 }

Entonces puede usarlo así:

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


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


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 por alguna razón todavía trabajas en Rails 2 (como yo), echa un vistazo a la publicación SO here .

Ofrece una secuencia de comandos para poner en inicializadores.


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


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