web-dev-qa-db-ja.com

Rails 3: "field-with-errors"ラッパーはページの外観を変更します。これを回避する方法は?

メール欄:

<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

この外観の変更を回避するにはどうすればよいですか?

129
Misha Moroshko

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
}

この変更を有効にするには、Railsサーバーを再起動します。

229
Ryan Bigg

div要素はブロック要素であるため、視覚的な違いが生じています。このスタイルをCSSファイルに追加して、インライン要素のように動作させます。

.field_with_errors { display: inline; }
99
dontangg

現在、このソリューションを使用して、初期化子に配置します。

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

これにより、追加の要素を作成せずに、適切なタグにクラス名を追加するだけで済みます。

70
Phobetron

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 }

または、UIに適したものに変更できます。

config.action_view.field_error_proc = Proc.new { |html_tag, instance| "<span class='field_with_errors'>#{html_tag}</span>".html_safe }
20
Dan Cheail

私はRails 5および Materialize-Sass で作業しており、Rails下の画像のようにフィールド検証が行われましたが、これは検証が失敗した入力フィールドに余分なdivが追加されたためです。

enter image description here

@Phobetronの回答を使用し、Hugo Demiglioの回答も変更します。これらのコードブロックにいくつかの調整を加えたところ、次のような場合にうまく機能します。

  • inputlabelの両方が独自の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属性の既存のクラスに追加され、ラベルに存在しない場合は作成されますまたは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

私と同じ状態の人に役立つといいのですが。

4
Alex Ventura

@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
4
Hugo Demiglio

一部のオブジェクトでこの恐ろしいことを無効にするオプションを作成しました

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

何らかの理由でまだ作業している場合、Rails 2(私と同じ))SO post here

初期化子を配置するスクリプトを提供します。

2
ScottJShea

心に留めておくべきことの1つは(今日この問題を解決していることを発見したように)、ラベルまたは入力フィールドを浮動させると(すべての入力フィールドを浮動させる場合)、ActionView:をオーバーライドしてもcssが壊れることです: 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;
}
2
Kevin Reeth

それがスタイリングのためだけである場合(divを気にしない)、これをcssに追加するだけです:

div.field_with_errors {
 display: inline;
}

divspanのように機能し、設計に干渉しません(divはブロック要素であるため– display: block;–デフォルトでは、閉じると新しい行が作成されます。 spaninlineであるため、そうではありません)。

1
user2985898

これは、@ 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'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
}

この方法は、フォーム全体で応答をスタイルするために、以前のすべての中で最も柔軟で目立たないものであることがわかりました。

1
dgilperez

スタイリングの問題のみの場合は、「field_with_errors」を上書きできます。しかし、それはアプリケーションの他のフォームに影響を与える可能性があるため、そのフィールドのみで「field_with_errors」クラスを上書きする方が適切です。

'parent_class'がフォームのエラーフィールドの親クラス(フォームのクラスまたはエラーフィールドの親要素のクラスのいずれか)の1つであることを考慮すると、

  .parent_class .field_with_errors {
    display: inline;
  }

問題を修正するだけでなく、アプリケーション内の他のフォームも邪魔しません。

OR

アプリケーション全体で「field_with_errors」のスタイルをオーバーライドする必要がある場合は、@ dontanggが言ったように、

.field_with_errors { display: inline; } 

修正を行います。それが役に立てば幸い :)

0
Prem

特定の要素のエラーをオフにしたいだけなら、例えばチェックボックス、これを行うことができます:

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
0
Tintin81