레일 위의 루비 f. 사용자 정의 속성이있는 옵션 선택


115

다음과 같은 양식 선택 문이 있습니다.

= f.select :country_id, @countries.map{ |c| [c.name, c.id] }

이 코드는 다음과 같습니다.

...
<option value="1">Andorra</option>
<option value="2">Argentina</option>
...

하지만 다음과 같이 내 옵션에 사용자 정의 HTML 속성을 추가하고 싶습니다.

...
<option value="1" currency_code="XXX">Andorra</option>
<option value="2" currency_code="YYY">Argentina</option>
...

2
Rails는 해당 기능을 제공하지 않으므로 해당 마크 업을 생성하려면 도우미를 생성해야합니다. 또한 언급 한 예제는 유효한 HTML이 아닙니다.
Augusto

내 예제는 유효한 html이 아닙니다. 원하는 결과를 얻으려면 내 방식을 변경해야합니다. thk!
el_quick

답변:


356

Rails는 기존 options_for_select 도우미를 사용하여 사용자 지정 속성을 추가하여 옵션을 선택할 수 있습니다. 귀하의 질문에 거의 코드가 있습니다. html5 데이터 속성 사용 :

<%= f.select :country_id, options_for_select(
    @countries.map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] }) %>

초기 선택 추가 :

<%= f.select :country_id, options_for_select(
    @countries.map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] }, 
    selected_key = f.object.country_id) %>

그룹화 된 옵션이 필요한 경우 다음과 같이 grouped_options_for_select 도우미를 사용할 수 있습니다 (@continents가 각 대륙 메서드가있는 대륙 개체의 배열 인 경우).

<%= f.select :country_id, grouped_options_for_select(
    @continents.map{ |group| [group.name, group.countries.
    map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] } ] }, 
    selected_key = f.object.country_id) %>

신용은 문서가 아니라 레일 소스를 읽음으로써 이것을 발견하는 것에 대해 게시 한 paul @ pogodan에게 가야합니다. https://web.archive.org/web/20130128223827/http://www.pogodan.com/blog/2011/02/24/custom-html-attributes-in-options-for-select


6

다음과 같이 할 수 있습니다.

= f.select :country_id, @countries.map{ |c| [c.name, c.id, { 'data-currency-code' => c.currency_code} ] }

맞지만 Anatortoise House의 답변에서 이미 언급되었습니다.
Kelvin

허용되는 대답은 루비를 사용하는 사용자 정의 속성을 설명하지 않습니다. 이것은 루비를 통해하는 방법을 보여주는 첫 번째 답변이기 때문에 더 좋습니다.
Nikhil Gupte 2013-06-02

5

이것은 Rails에서 직접 가능하지 않으며, 사용자 지정 속성을 생성하기 위해 자신 만의 헬퍼를 생성해야합니다. 즉, 원하는 작업을 수행하는 방법에는 두 가지가 있습니다.

(1) HTML5에서 사용자 정의 속성 이름 사용. HTML5에서는 사용자 정의 속성 이름 을 가질 수 있지만 앞에 'data-'를 추가해야합니다. 이러한 사용자 정의 속성은 양식과 함께 제출되지 않지만 Javascript에서 요소에 액세스하는 데 사용할 수 있습니다. 이 작업을 수행하려면 다음과 같은 옵션을 생성하는 도우미를 만드는 것이 좋습니다.

<option value="1" data-currecy-code="XXX">Andorra</option>

(2) 사용자 지정 분할과 함께 값을 사용하여 추가 데이터를 제출합니다. 실제로 통화 코드를 제출하려면 다음과 같이 선택 상자를 만드는 것이 좋습니다.

= f.select :country_id, @countries.map{ |c| [c.name, "#{c.id}:#{c.currency_code}"] }

이렇게하면 다음과 같은 HTML이 생성됩니다.

<option value="1:XXX">Andorra</option>
<option value="2:YYY">Argentina</option>

그런 다음 컨트롤러에서 구문 분석 할 수 있습니다.

@id, @currency_code = params[:country_id].split(':')

3
좋은 대답입니다. 나는 접근 번호 1을 선택하고 다른 사람을 도울 경우를 대비하여 어떻게 도우미를 만들 었는지 블로그에 올렸습니다. redguava.com.au/2011/03/...
조엘 프리드 랜더에게

다른 댓글 작성자와 동의하십시오-아래 Anatortoise의 답변을 참조하십시오!
Jacob

23
>>>>>>>>>>>>> 잘못된 답변 ... 계속 스크롤링 <<<<<<<<<<<<
stevenspiel

1
이것은 Rails에서 직접 가능합니다. 참조 : stackoverflow.com/a/9076805/380607
Magne 2015

Pan, 오해의 소지가있는 답변을 삭제하십시오.
vemv

4

추가 속성 해시는 Rails 3에서만 지원됩니다.

Rails 2.x 를 사용 중이고 재정의하려는 경우options_for_select

기본적으로 Rails 3 코드를 복사했습니다. 다음 세 가지 방법을 재정의해야합니다.

def options_for_select(container, selected = nil)
    return container if String === container
    container = container.to_a if Hash === container
    selected, disabled = extract_selected_and_disabled(selected)

    options_for_select = container.inject([]) do |options, element|
      html_attributes = option_html_attributes(element)
      text, value = option_text_and_value(element)
      selected_attribute = ' selected="selected"' if option_value_selected?(value, selected)
      disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled)
      options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{html_escape(text.to_s)}</option>)
    end

    options_for_select.join("\n").html_safe
end

def option_text_and_value(option)
  # Options are [text, value] pairs or strings used for both.
  case
  when Array === option
    option = option.reject { |e| Hash === e }
    [option.first, option.last]
  when !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last)
    [option.first, option.last]
  else
    [option, option]
  end
end

def option_html_attributes(element)
  return "" unless Array === element
  html_attributes = []
  element.select { |e| Hash === e }.reduce({}, :merge).each do |k, v|
    html_attributes << " #{k}=\"#{ERB::Util.html_escape(v.to_s)}\""
  end
  html_attributes.join
end

좀 지저분하지만 옵션입니다. 이 코드를라는 도우미 모듈에 RailsOverrides넣은 다음 ApplicationHelper. 원하는 경우 플러그인 / 젬을 사용할 수도 있습니다.

한 가지 문제점은 이러한 메서드를 활용하려면 항상 options_for_select직접 호출해야한다는 것 입니다. 다음과 같은 단축키

select("post", "person_id", Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] })

오래된 결과를 얻을 것입니다. 대신 다음과 같아야합니다.

select("post", "person_id", options_for_select(Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] }))

다시 한 번 훌륭한 솔루션은 아니지만 매우 유용한 데이터 속성을 얻을 가치가있을 수 있습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.