Rails 3: o wrapper “field-with-errors” altera a aparência da página. Como evitar isso?

Campo de email:

  

se parece com isso:

sem erro

Mas, se a validação de email falhar, ela se torna:

 

que se parece com isso:

with_error

Como eu poderia evitar essa mudança de aparência?

Você deve replace o ActionView::Base.field_error_proc . Está atualmente definido como isso dentro do ActionView::Base :

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

Você pode sobrescrevê-lo colocando isto na class do seu aplicativo dentro de config/application.rb :

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

Reinicie o servidor rails para que esta alteração tenha efeito.

A diferença visual que você está vendo está acontecendo porque o elemento div é um elemento de bloco. Adicione este estilo ao seu arquivo CSS para que ele se comporte como um elemento in-line:

 .field_with_errors { display: inline; } 

Eu atualmente uso essa solução, colocada em um 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 

Isso me permite simplesmente adicionar um nome de class à tag apropriada, sem criar elementos adicionais.

O código extra está sendo adicionado pelo ActionView::Base.field_error_proc . Se você não estiver usando field_with_errors para estilizar seu formulário, poderá substituí-lo em application.rb :

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

Como alternativa, você pode alterá-lo para algo que atenda à sua interface do usuário:

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

Além da resposta @phobetron, que não funciona quando você tem outra tag com o atributo class, como .

Eu fiz algumas alterações em sua solução:

 # 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 

Eu estou trabalhando com Rails 5 e Materialize-Sass e estou recebendo alguns problemas com o comportamento padrão do Rails para tratar validações de campo com falha como na imagem abaixo e foi por causa do div extra adicionado aos campos de input onde a validação falhou.

insira a descrição da imagem aqui

Trabalhando com o @Phobetron responda e modifique a resposta de Hugo Demiglio também. Fiz alguns ajustes nesses blocos de código e obtive algo funcionando bem nos seguintes casos:

  • Se a input e o label tiverem seu próprio atributo de class qualquer lugar
  • Se as tags de input ou label não tiverem um atributo de class
  • se a tag label tiver outra tag dentro com o class attribute

Em todos esses casos, a class de error será adicionada às classs existentes no atributo de class se existir, ou será criada, se não estiver presente no label ou nas tags de 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 possa ser útil para alguém com as mesmas condições que eu.

Se por algum motivo você ainda estiver trabalhando no Rails 2 (como eu), confira o post do SO aqui .

Ele oferece um script para colocar em inicializadores.

Uma coisa a ter em mente (como descobri ao trabalhar com isso hoje) é que se você flutuar o label ou os campos de input (estou flutuando todos os campos de input), o css será interrompido mesmo se você replace o ActionView :: Base.field_error_proc.

Uma alternativa é deixar um nível mais profundo na formatação CSS da seguinte forma:

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

Eu fiz uma opção para desativar essa coisa terrível para alguns objects

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

Então, pode usá-lo assim:

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

Esta é a minha solução a partir da resposta da Phobetron. Colocando este código em application.rb , suas tags

e geradas pelas chamadas form.error :p correspondentes receberão a tag css fields_with_errors . O restante receberá a class 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 } 

Achei assim o mais flexível e não-obstrutivo de todos os anteriores para estilizar a resposta em meus formulários.

Se é apenas para fins de estilo (você não se importa o div ), você pode simplesmente adicionar isso ao seu CSS:

 div.field_with_errors { display: inline; } 

O div irá agir como um span e não irá interferir com o seu design (já que div é um elemento block – display: block; – por padrão, ele causará uma nova linha depois que ele for fechado; span é inline , então não ).

Se for apenas sobre problemas de estilo, podemos sobrescrever “field_with_errors”. Mas como isso pode afetar outras formas em nosso aplicativo, é melhor sobrescrever a class “field_with_errors” apenas nesse formulário.

Considerando que ‘parent_class’ é um da class pai para o campo de erro do formulário (qualquer class ou class de formulário de qualquer elemento pai para o campo error), então

  .parent_class .field_with_errors { display: inline; } 

Ele irá corrigir o problema, assim como não irá atrapalhar outras formas em nosso aplicativo.

OU

Se precisarmos replace o estilo de “field_with_errors” para todo o aplicativo, então, como @dontangg disse,

 .field_with_errors { display: inline; } 

vai fazer a correção. Espero que ajude 🙂