2010-04-12 24 views
23

有沒有辦法,我可以創建自定義表單幫手,這樣的替代方法:自定義表單helper

special_field_tag :object, :method 

我能做到這樣的:

form.special_field :method 

回答

47

是的,你可以添加到FormBuilder類並獲得傳遞給form_for的對象的訪問權限。我這樣做了很多事情:日期,時間,測量,等這裏有一個例子:

class ActionView::Helpers::FormBuilder 
    include ActionView::Helpers::TagHelper 
    include ActionView::Helpers::FormTagHelper 
    include ActionView::Helpers::FormOptionsHelper 
    include ActionView::Helpers::CaptureHelper 
    include ActionView::Helpers::AssetTagHelper 

    # Accepts an int and displays a smiley based on >, <, or = 0 
    def smile_tag(method, options = {}) 
    value = @object.nil? ? 0 : @object.send(method).to_i 
    options[:id] = field_id(method,options[:index]) 
    smiley = ":-|" 
    if value > 0 
     smiley = ":-)" 
    elsif smiley < 0 
     smiley = ":-(" 
    end 
    return text_field_tag(field_name(method,options[:index]),options) + smiley 
    end 

    def field_name(label,index=nil) 
    output = index ? "[#{index}]" : '' 
    return @object_name + output + "[#{label}]" 
    end 

    def field_id(label,index=nil) 
    output = index ? "_#{index}" : '' 
    return @object_name + output + "_#{label}" 
    end 

end 

您可以使用這樣的:

<% form_for @quiz do |f| %> 
    <%= f.smile_tag(:score) %> 
<% end %> 

有產生了一些實例變量通過Rails的,你可以在這些輔助方法訪問:

  • @object - 通過的形式指定
  • @object_name模型對象 - 次的類名e object
  • @template - 我認爲它是ActionView的一個實例,您可以繞過模板上調用方法添加的所有包含。還沒有嘗試過。
  • @options - 選項傳遞給FormBuilder當其被創建的form_for叫

我寫的FIELD_ID和FIELD_NAME方法創建的HTML輸入元素這些屬性相同的方式,定期做幫手,我確定有一種方法可以與Rails使用的相同方法綁定,但我還沒有找到它。

天空是你可以用這些幫助器方法做的限制,它們只是返回字符串。您可以一次創建完整的HTML表格或頁面,但您最好有一個很好的理由。

這個文件應該在應用程序中添加/傭工文件夾

+3

您也可以繼承FormBuilder,然後在每個表單的基礎上使用您的自定義構建器: <%form_for @person,:builder => MyFormBuilder do | f | %> ... <% end %> – nfm 2010-04-13 00:43:58

+1

或者全局,ActionView :: Base.default_form_builder = MyFormBuilder – graywh 2012-04-10 19:47:52

+0

你把這個文件放在哪裏?你會把班級變得難以言喻嗎? – jackyalcine 2012-08-14 17:30:43

6

@Tilendor,感謝這麼多的指針。下面是一個使用的Rails 4.1枚舉來自動填充選擇標籤的選項的enum_select形式標籤輔助的示例:

# helpers/application_helper.rb 
module ApplicationHelper 
    class ActionView::Helpers::FormBuilder 
    # http://stackoverflow.com/a/2625727/1935918 
    include ActionView::Helpers::FormTagHelper 
    include ActionView::Helpers::FormOptionsHelper 
    def enum_select(name, options = {}) 
     # select_tag "company[time_zone]", options_for_select(Company.time_zones 
     # .map { |value| [value[0].titleize, value[0]] }, selected: company.time_zone) 
     select_tag @object_name + "[#{name}]", options_for_select(@object.class.send(name.to_s.pluralize) 
     .map { |value| [value[0].titleize, value[0]] }, selected: @object.send(name)) 
    end 
    end 
end 

最棘手的構建體是@object.class.send(name.to_s.pluralize)產生可用的值的散列(例如,Company.time_zones)。將它放入helpers/application_helper.rb使其自動可用。它用於這樣的:

在文本字段
<%= f.label :billing_status %>: 
<%= f.enum_select :billing_status %><br /> 
2

我們的應用程序中顯示的電話號碼,我們想省略國家代碼爲國內數字。我正在使用表單助手。看完這個和軌道源的位,我來到這個解決方案:

class ActionView::Helpers::FormBuilder 
    def phone_text_field name, options = {} 
    value = object.public_send(name).to_s 
    if value.start_with? "9" # national number 
     value = value[1..-1] 
     options["value"] = value 
    end 
    text_field name, options 
    end 
end 

我把這個應用程序/傭工/ application_helper.rb和使用它像我使用text_field()幫手。希望這可以幫助某人。