Rails 3: обертка с полем с ошибками изменяет внешний вид страницы. Как этого избежать?

Поле электронной почты:

  

выглядит так:

without_error

Но, если проверка электронной почты не удалась, она становится:

 

который выглядит следующим образом:

with_error

Как я мог избежать этого изменения внешнего вида?

Вы должны переопределить ActionView::Base.field_error_proc . В настоящее время он определяется как это в ActionView::Base :

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

Вы можете переопределить его, поместив это в class вашего приложения внутри config/application.rb :

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

Перезагрузите сервер рельсов, чтобы это изменение вступило в силу.

Визуальная разница, которую вы видите, происходит потому, что элемент div является блочным элементом. Добавьте этот стиль в свой CSS-файл, чтобы заставить его вести себя как встроенный элемент:

 .field_with_errors { display: inline; } 

В настоящее время я использую это решение, помещенное в инициализатор:

 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 

Это позволяет мне просто добавить имя classа в соответствующий тег, не создавая дополнительных элементов.

Дополнительный код добавляется ActionView::Base.field_error_proc . Если вы не используете field_with_errors для field_with_errors своей формы, вы можете переопределить ее в application.rb :

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

Кроме того, вы можете изменить его на то, что соответствует вашему пользовательскому интерфейсу:

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

Помимо ответа @phobetron, который не работает, если у вас есть другой тег с атрибутом classа, например .

Я сделал некоторые изменения в его решении:

 # 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 

Я работаю с Rails 5 и Materialize-Sass, и у меня возникают некоторые проблемы с поведением по умолчанию из Rails для обработки неудачных проверок полей, как показано на рисунке ниже, и это связано с тем, что дополнительный div добавлен в поля ввода, где проверка не удалась.

введите описание изображения здесь

Работа с @Phobetron отвечает и модифицирует ответ Хьюго Демильо. Я внес некоторые коррективы в эти блоки кода, и я получаю что-то хорошее в следующих случаях:

  • Если и input и label имеют свой собственный атрибут class любом месте
  • Если tags input или метки не имеют атрибута class
  • если тег метки имеет другой тег внутри с class attribute

Во всех этих случаях class error будет добавлен к существующим classам в атрибуте class если он существует, или он будет создан, если он не присутствует в метках или тегах ввода .

 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 

Надеюсь, это может быть полезно для кого-то с такими же условиями, как я.

Если по какой-то причине вы все еще работаете над Rails 2 (например, я), проверьте здесь сообщение SO.

Он предлагает скрипт для ввода инициализаторов.

Одна вещь, о которой нужно помнить (поскольку я обнаружил, что работаю над этим сегодня), заключается в том, что если вы плаваете либо метку, либо поля ввода (я плаваю по всем полям ввода справа), css будет ломаться, даже если вы переопределите ActionView :: Base.field_error_proc.

Альтернативой является понижение уровня глубже в форматировании CSS следующим образом:

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

Я сделал выбор, чтобы отключить эту ужасную вещь для некоторых объектов

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

Поэтому можно использовать его так:

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

Это мое решение, основанное на ответе @ Phobetron. Помещая этот код в application.rb , tags

и сгенерированные соответствующим form.error :p , получат тег fields_with_errors css. Остальное получит class 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 } 

Я нашел этот способ наиболее гибким и ненавязчивым из всех предыдущих, чтобы сформировать ответ в моих формах.

Если это просто для стилизации (вы не против div ), вы можете просто добавить это в свой css:

 div.field_with_errors { display: inline; } 

div будет действовать как span и он не будет мешать вашему дизайну (поскольку div является блочным элементом – display: block; – по умолчанию он вызывает новую строку после ее закрытия; spaninline , поэтому он не ).

Если речь идет только о проблемах с стилем, мы можем перезаписать «field_with_errors». Но поскольку это может повлиять на другие формы в нашем приложении, лучше переписать class «field_with_errors» только в этой форме.

Учитывая, что «parent_class» является одним из родительских classов для поля ошибки формы (class или class формы любого из родительского элемента для поля ошибки), тогда

  .parent_class .field_with_errors { display: inline; } 

Он также устранит проблему, а также не нарушит любые другие формы в нашем приложении.

ИЛИ

Если нам нужно переопределить стиль «field_with_errors» для всего приложения, то, как сказал @dontangg,

 .field_with_errors { display: inline; } 

будет делать исправление. Надеюсь, поможет 🙂

Давайте будем гением компьютера.