Rails 3 : "오류가있는 필드"래퍼가 페이지 모양을 변경합니다. 이것을 피하는 방법?


131

이메일 입력란 :

<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

이 모양 변경을 어떻게 피할 수 있습니까?


안녕 @ misha-moroshko, 여기에 설명 된대로 부모 수준에서 오류 클래스를 추가하려고 합니다 . (가) byebug를 사용하여 코드를 레일 그러나 나는 즉시 분실에 나는 그 필드에 부모가있는 경우 확인하여 설정에 약간의 현명한 방법이 동작을 원 .. 다이빙 시도 ...
SanjiBukai

답변:


235

재정의해야합니다 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
}

이 변경 사항을 적용하려면 레일 서버를 다시 시작하십시오.


4
하나의 작은 질문 : 왜 label와가 둘 다 input포장되어 있습니까? Rails는 어떻게 포장해야합니까?
Misha Moroshko

4
이것은 아마도 필드 레이블에 오류가있는 스타일을 지정할 수 있도록하기위한 것입니다. : 또한, 당신이 그것을 말해 때문에 필드는 당신을 위해 양식을 만들고있는 자원의 어떤 속성에 속하는 무엇을 포장 아는 레일 f.label :passwordf.password_field :password@resource.errors있을 것 [:password]오류 세트.
Mosselman

3
당신은 트위터 부트 스트랩 작업하고, 또는 당신이 field_error_proc에서 할 수있는 일의 또 다른 예를 원하는 경우에,이 멋진 요점을 checke : gist.github.com/1464315
라이언 샌드

2
왜 html_tag.html_safe가 아닌 "# {html_tag}". html_safe를해야합니까?
Anurag

3
Anurag : html_tag가 0이 아니거나 문자열 이외의 것이면 일반 html_tag.html_safe에서 오류가 발생합니다. 에 넣어 "# {HTML_TAG}는"암시 잘하면 다음 html_safe에 응답 할 수 문자열 반환 html_tag.to_s 호출
sockmonk

100

div요소가 블록 요소 이므로 시각적 차이가 발생합니다 . 인라인 요소처럼 작동하도록 CSS 파일에이 스타일을 추가하십시오.

.field_with_errors { display: inline; }

2
이것은에서 display:사용되는 속성 (및 기타 레이아웃 스타일)을 무시하기 때문에 최선의 해킹 html_tag입니다.
Ryan

1
나는 그것을 핵으로 보지 않는다. display이 CSS가 추가되기 전에 속성은 사용되는 block바람직하지 않은 시각적 차이를 유발한다. 태그의 다른 레이아웃 스타일은 무효화하지 않습니다. 그러나 Ryan Bigg의 답변은 필드를 오류로 감싸는 태그를 변경 / 제거하려는 경우 완벽합니다.
dontangg

그러나이 방법을 시도했지만 <p> 태그 안에 필드가 있으면 <p> 내의 <div>가 무엇이든간에 줄을 끊기 때문에 작동하지 않는 것 같습니다 (적어도 Firefox에서는 작동하지 않음). Biggs 솔루션을 사용하면 <div를 <span으로 바꾸는 것만으로도 트릭을 수행하는 것 같습니다.
jpw

72

나는 현재이 솔루션을 사용하여 초기화 프로그램에 배치했습니다.

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

이를 통해 추가 요소를 만들지 않고도 클래스 이름을 해당 태그에 추가 할 수 있습니다.


2
오류 필드를 눈에 잘 띄지 않게 사용하는 것이 좋습니다.
Ryan

1
레일에서 작동 4.0.3.
Yuki Matsukura

1
나를 위해 일했다. 그래도 변경 사항을 알기 위해 레일 서버를 다시 시작해야했습니다 :)
Jezen Thomas

1
이 솔루션을 좋아했지만에 다른 태그가 있으면 작동하지 않습니다 label.
Caio Tarifa

안녕 @Phobetron, 실제로 이것은 좋은 해결책입니다. 여기에 설명 된 것과 같이 부모 수준에서 해당 클래스를 추가하는 방법을 검색합니다 . 난 레일즈 코드에 뛰어 들었지만 즉시 byebug로 렌더링 프로세스를 수행 할 수 없다는 것을 잃어 버렸습니다. 이것이 실제로 가능합니까?
산 지부 카이

20

에 의해 추가 코드가 추가되고 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 }

이것은 나를 위해 잘 작동합니다. 트위터 부트 스트랩과 함께 사용하기위한 가장 우아한 솔루션 인 것 같습니다
Avishai

5

Rails 5 및 Materialise-Sass 와 함께 일하고 있으며 아래 이미지와 같이 실패한 필드 유효성 검사를 처리하기 위해 Rails의 기본 동작과 관련된 문제가 발생 div했습니다. 이는 유효성 검사가 실패한 입력 필드에 추가로 인해 발생했습니다.

여기에 이미지 설명을 입력하십시오

@Phobetron 답변으로 작업하고 Hugo Demiglio의 답변도 수정하십시오. 해당 코드 블록을 조정하여 다음과 같은 경우에 잘 작동합니다.

  • 두 경우 input와는 label자신이 class속성 어디서나
    • <input type="my-field" class="control">
    • <label class="active" for="...">My field</label>
  • 는 IF 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

나는 그것이 나와 같은 조건을 가진 사람에게 유용 할 수 있기를 바랍니다.


4

@phobetron answer 외에도 클래스 속성이있는 다른 태그가있는 경우 작동하지 않습니다 <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

그러나 필드에 클래스 속성이없는 경우 작동하지 않습니다.
mizurnix

2

어떤 이유로 든 여전히 Rails 2에서 일하고 있다면 (예 : 나는) SO 게시물을 확인 하십시오. .

이니셜 라이저에 넣을 스크립트를 제공합니다.


2

명심해야 할 한 가지는 (오늘 내가이 작업을 통해 발견 한 바와 같이) 레이블 또는 입력 필드를 플로팅하면 (모든 입력 필드를 올바르게 플로팅하고 있음) 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

일부 객체 에서이 끔찍한 것을 비활성화하는 옵션을 만들었습니다.

# 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

1

이것은 @Phobetron의 답변 위에 구축 된 솔루션입니다. 이 코드를 배치 application.rb, 당신 <p><span>대응에 의해 생성 된 태그 form.error :p호출이 수신됩니다 fields_with_errorsCSS 태그를. 나머지는 errorCSS 클래스 를받습니다 .

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

스타일링 목적이라면 (을 신경 쓰지 않음 div) CSS에 추가하면됩니다.

div.field_with_errors {
 display: inline;
}

div유사한 역할을 span하고 그것은 당신의 디자인을 방해하지 않을 것이다 (이후 div블록 요소입니다 - display: block;- 기본적으로 그것을 종료 후, 그것은 새로운 라인을 일으킬 것입니다 span것입니다 inline그것은하지 않습니다, 그래서).


1

확인란 과 같은 특정 요소에 대한 오류를 끄려면 다음과 같이하십시오.

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

스타일링 문제에 대해서만 "field_with_errors"를 덮어 쓸 수 있습니다. 그러나 응용 프로그램의 다른 양식에 영향을 줄 수 있으므로 "field_with_errors"클래스를 해당 양식으로 만 덮어 쓰는 것이 좋습니다.

'parent_class'가 양식의 오류 필드에 대한 상위 클래스 중 하나 (오류 클래스에 대한 양식의 클래스 또는 상위 요소의 클래스) 중 하나를 고려한 다음

  .parent_class .field_with_errors {
    display: inline;
  }

문제를 해결하고 응용 프로그램의 다른 형식도 방해하지 않습니다.

또는

전체 응용 프로그램에 대해 "field_with_errors"스타일을 재정의해야하는 경우 @dontangg가 말했듯이,

.field_with_errors { display: inline; } 

수정을 할 것입니다. 그것이 도움이되기를 바랍니다 :)


0

field_error_proc전체 애플리케이션 을 변경하지 않으려는 경우 jQuery의 랩 해제 는 다음과 같은 특정 문제 영역에 대해보다 구체적인 솔루션을 제공 할 수 있습니다.

$('FORM .field_with_errors > INPUT[type="checkbox"]').unwrap();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.