概要
RailsではValidation
エラーが発生したフォームに、自動でfield_with_errors
クラスを割り当ててくれます。某チュートリアルでは、これにBootstrapのスタイルを適用することで、簡単に良い感じにする方法が紹介されています。
しかし、紹介されている方法はBootstrap2の書き方であるため、Bootstrap3を使用している場合はうまく動作しません。
Bootstrap2での実装
Rails Tutorialの7章にある通り、SCSS
で.field_with_errors
に.control-group
と.error
を追加してあげると、エラー時に良い感じに色をつけてくれるようになります。erb
側では特に何も設定する必要はありません。
new.html.erb<%= form_for(@user) do |f| %> <%= f.label :name %> <%= f.text_field :name %> <%= f.label :email %> <%= f.text_field :email %> <%= f.label :password %> <%= f.password_field :password %> <%= f.label :password_confirmation, "Confirmation" %> <%= f.password_field :password_confirmation %> <%= f.submit "Create my account", class: "btn btn-large btn-primary" %> <% end %>
custom.css.scss.field_with_errors { @extend .control-group; @extend .error; }
Bootstrap3での実装
Bootstrap3では.control-group
と.error
というクラスは消え去りました。公式サイトを見たところ、多分次のように名前が変わっています。
Bootstrap2 | Bootstrap3 |
---|---|
.control-group |
.form-group |
.error |
.has-error |
なんと、これを変更しただけではうまく動作しません。
Sass/Rails form validation with Bootstrap 3のAnswerを読むに、どうやら、素の.has-error
のスタイルは無くなってしまったことが原因のようです。
したがって、それぞれのコンポーネントにcontrol-label
やform-control
あたりの、適切なクラスを割り振ってやる必要があります。
具体的には、以下のようにクラスを追記しました。
<div class="span6 offset3">
<%= form_for(@user) do |f| %>
<%= f.label :name, class: "control-label"%>
<%= f.text_field :name, class: "form-control" %>
<%= f.label :email, class: "control-label"%>
<%= f.text_field :email, class: "form-control" %>
<%= f.label :password, class: "control-label"%>
<%= f.password_field :password, class: "form-control" %>
<%= f.label :password_confirmation, "Confirmation", class: "control-label" %>
<%= f.password_field :password_confirmation, class: "form-control" %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
.field_with_errors {
@extend .form-group;
@extend .has-error;
}
これで無事、field_with_errors
クラスにBootstrap3の.has-error
スタイルを適用することができました。
補足
.form-group
の役割
こちらは削除しても動きました。正直何をしてくれてるのか理解せずに書いていたので、とりあえず削除しています。
collection_select
でのクラスの設定
上記のコードの通りに、collection_select
にクラスを設定しようとしても、全く反映されませんでした。案の定、全く同じ現象に遭遇している方がいました。
そちらを参考に、こんな感じで実装してみました。
<%= f.collection_select(:type_id, Type.all, :id, :name,
{ prompt: "選択してください }, { class: "form-control" }) %>