背景
- Rails では、バリデーションエラーのあった項目はデフォルトで
<div class="field_with_errors">で囲まれる - この挙動は、
config/application.rbにconfig.action_view.field_error_procを指定することで変更できる- 意図しない
<div>が入ることでデザインが崩れるとか、 Bootstrap を使っているときに.has-errorをつけたいとか気になったら動作を変えたくなってくる
- 意図しない
-
config.action_view.field_error_procと検索すると「<div class="field_with_errors">をつけないようにする」とか「class名をfield_with_errorsから変える」ようなものばかりがヒットする。- → 実はもっといろんなことができる!
やりたいこと
ということで、バリデーションエラーがあったらテキストフィールドのすぐ下にエラーメッセージを表示するようにしてみましょう。
この例では Bootstrap を使っているので、
- フィールド全体を
.has-errorで囲む - エラーメッセージは Validation states のように
.help-blockを使って表示する
という方針で実装しました。
結果
config/application.rb に実装するだけで期待通りに動きます:
config/application.rb
config.action_view.field_error_proc = Proc.new do |html_tag, instance|
if instance.kind_of?(ActionView::Helpers::Tags::Label)
# skip when label
html_tag.html_safe
else
"<div class=\"has-error\">#{html_tag}<span class=\"help-block\">#{instance.error_message.first}</span></div>".html_safe
end
end
View にはエラーメッセージの表示について一切実装する必要はありません:
view/hoges/new.html.haml
.form-group
= f.label :name
%span.label.label-danger 必須
= f.text_field :name, placeholder: '例:あべ しんぞう', class: 'form-control', required: true
こんなかんじで表示されるようになります:
解説
-
instanceはActionView::Helpers::Tags::Baseのサブクラスになるっぽい -
instanceのクラスを調べることによって、ラベルの場合には何もせずそのまま返す -
instance.error_messageにバリデーションの内容が入っているので、取り出す
