Rails 3: обертка с полем с ошибками изменяет внешний вид страницы. Как этого избежать?
Поле электронной почты:
<label for="job_client_email">Email: </label>
<input type="email" name="job[client_email]" id="job_client_email">
выглядит так:
![without_error]()
Но, если проверка электронной почты не удалась, она становится:
<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>
который выглядит следующим образом:
![with_error]()
Как я мог избежать этого изменения внешнего вида?
Ответы
Ответ 1
Вы должны переопределить ActionView::Base.field_error_proc
. В настоящее время этот параметр определяется как ActionView::Base
:
@@field_error_proc = Proc.new{ |html_tag, instance|
"<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
}
Вы можете переопределить его, поместив это в свой класс приложения внутри config/application.rb
:
config.action_view.field_error_proc = Proc.new { |html_tag, instance|
html_tag
}
Перезагрузите сервер рельсов, чтобы это изменение вступило в силу.
Ответ 2
Визуальная разница, которую вы видите, происходит потому, что элемент div
является блочным элементом. Добавьте этот стиль в свой CSS файл, чтобы он вел себя как встроенный элемент:
.field_with_errors { display: inline; }
Ответ 3
В настоящее время я использую это решение, помещенное в инициализатор:
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
Это позволяет мне просто добавить имя класса в соответствующий тег, не создавая дополнительных элементов.
Ответ 4
Добавочный код добавляется ActionView::Base.field_error_proc
. Если вы не используете 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| "<span class='field_with_errors'>#{html_tag}</span>".html_safe }
Ответ 5
Кроме ответа @phobetron, который не работает, если у вас есть другой тег с атрибутом класса, например <label for="..."><i class="icon my-icon"></i>My field</label>
.
Я сделал некоторые изменения в его решении:
# 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
Ответ 6
Я работаю с Rails 5 и Materialize-Sass, и у меня возникают некоторые проблемы с поведением по умолчанию из Rails для обработки неудачных проверок полей как показано на рисунке ниже, и это было связано с добавлением дополнительного div
к полям ввода, в которых не удалось выполнить проверку.
![введите описание изображения здесь]()
Работа с @Phobetron ответом и изменением ответа Hugo Demiglio тоже. Я внес некоторые изменения в эти блоки кода, и я получаю что-то хорошее в следующих случаях:
- Если оба
input
и label
имеют свой собственный атрибут class
в любом месте
-
<input type="my-field" class="control">
-
<label class="active" for="...">My field</label>
- Если теги
input
или label
не имеют атрибута class
-
<input type="my-field">
-
<label for="...">My field</label>
- если тег
label
имеет другой тег внутри с class attribute
-
<label for="..."><i class="icon-name"></i>My field</label>
Во всех этих случаях класс error
будет добавлен к существующим классам в атрибуте 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
Я надеюсь, что это может быть полезно для кого-то с такими же условиями, как я.
Ответ 7
Если по какой-то причине вы все еще работаете над Rails 2 (например, я), ознакомьтесь с SO post здесь.
Он предлагает script для ввода инициализаторов.
Ответ 8
Одна вещь, о которой нужно помнить (поскольку я обнаружил, что работаю через это сегодня), заключается в том, что если вы плаваете либо метку, либо поля ввода (я плаваю по всем полям ввода справа), 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;
}
Ответ 9
Я сделал вариант отключить эту ужасную вещь для некоторых объектов
# 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
}
Так можно использовать его следующим образом:
@user.skip_field_error_wrapper = true
form_for(@user) do |f|
...
end
Ответ 10
Это мое решение, построенное поверх ответа @Phobetron. Помещая этот код в application.rb
, теги <p>
и <span>
, сгенерированные соответствующими вызовами form.error :p
, получат тег fields_with_errors
css. Остальные получат класс error
CSS.
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 and span 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
}
Я нашел этот способ наиболее гибким и ненавязчивым из всех предыдущих, чтобы сформировать ответ в моих формах.
Ответ 11
Если это просто для стилизации (вы не против div
), вы можете просто добавить это в свой css:
div.field_with_errors {
display: inline;
}
div
будет действовать как a span
, и он не будет мешать вашему дизайну (поскольку div
является блочным элементом - display: block;
- по умолчанию, он вызовет новую строку после ее закрытия; span
есть inline
, так что это не так).
Ответ 12
Если речь идет только о проблемах с стилями, мы можем перезаписать "field_with_errors" . Но поскольку это может повлиять на другие формы в нашем приложении, лучше переписать класс "field_with_errors" только в этой форме.
Учитывая, что "parent_class" является одним из родительских классов для поля формы формы (либо класса формы, либо класса любого родительского элемента для поля ошибки), то
.parent_class .field_with_errors {
display: inline;
}
Он исправит проблему, а также не нарушит любые другие формы в нашем приложении.
ИЛИ
Если нам нужно переопределить стиль "field_with_errors" для всего приложения, то, как сказал @dontangg,
.field_with_errors { display: inline; }
выполнит исправление. Надеюсь, это поможет:)
Ответ 13
Если вы просто хотите отключить ошибки для определенных элементов, например, флажки, вы можете сделать это:
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
doc = Nokogiri::HTML::Document.parse(html_tag)
if doc.xpath("//*[@type='checkbox']").any?
html_tag
else
"<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
end
end