2009-06-21 42 views
1

我希望能夠生成以下標記:在創建自定義表單標籤字段

<label for="field">Something <span class="hint">Field hint</span></label> 

從下面的代碼:

form_for ... do |f| 
    f.label :field, :hint => "Field hint" 
end 

到目前爲止,我已經創建了一個初始化器存儲其自定義的功能重新開啓::的ActionView ::助手和FormBuilder改變標籤的方法,但是我不知道什麼是最好的方式來實際獲得跨度到文本的標籤。如果我嘗試將文本直接放入文件夾中,則正確地如此,就會漏掉內容。

我挺想利用現有的基礎設施的標籤,因爲它擁有所有的驗證錯誤的支持。這排除了使用content_tag並自己生成它(這會工作,但似乎不是......)。

回答

3

除了更改默認的建設者,你應該創建一個自定義生成器,並將其傳遞到與形式:建設者參數。

class HintFormBuilder < ActionView::Helpers::FormBuilder 
end 

form_for @resource, :builder => HintFormBuilder do |f| 
# ... 
end 

該提示構建器繼承了所有FormBuilder功能,包括驗證,錯誤消息等。現在,您應該更改需要更改的內容以便自定義行爲。 這是一個非常原始的草案。

class HintFormBuilder < ActionView::Helpers::FormBuilder 

    (%w(label)).each do |selector| 
    src = <<-end_src 
     def #{selector}(method, options = {}) 
     hint = options.delete(:hint) 
     returning(super) do |element| 
      # replace here the value of element with hint 
      # if hint != nil 
      # remember to use gsub! and not gsub 
     end 
     end 
    end_src 
    class_eval src, __FILE__, __LINE__ 
    end 

end 

編輯基於第一評論:

它總是一個好主意,沒本事的Rails內部,因爲你可能需要使用,現在還是將來,插件或功能依賴原來的行爲。如果您不想在表單中手動追加生成器,則可以創建一個幫助器。

高清search_form_for(record_or_name_or_array,* ARGS,& PROC) 選項= {:建設者=> HintFormBuilder}

form_for(record_or_name_or_array, 
     *(args << options), 
     &proc) 

如果你想重新打開原來的類,而不是,我會建議創造一種新方法。此解決方案也適用於自定義幫助程序,並且您可以自定義它,而無需使用gsub!響應。是的,gsub!就是這樣做的,因爲擴展原始方法時,你只能訪問方法/選項和結果的常見方式,沒有值(即由@object變量注入)。

class ActionView::Helpers::FormBuilder 

    def label_with_hint(method, text = nil, options = {}) 
    hint = options.delete(:hint) 
    # do your own customizations... 
    @template.label(@object_name, method, text, objectify_options(options)) 
    end 

end 

編輯:我錯了,你可以通過自定義文本作爲參數,所以你不需要GSUB!返回的字符串。我被text_field標記弄糊塗了。 此時,您可以使用第一個(使用/不使用自定義方法的子類),第二個(黑客內部使用)或第三個選項(使用自定義方法使用黑客內部處理)並截取文本值,然後將其發送到@ template.label。

另請注意,文本可以爲零。如果爲零,則該值是從方法自動生成的。你應該知道這一點。

+0

我真的不希望有指定表單生成器我想每個表單上使用。此外,我敢肯定,必須有比gsub-ing的價值更好的方式... – jonnii 2009-06-22 00:02:27

+0

我不知道爲什麼有人投這個帖子。 – jonnii 2009-06-24 13:55:03

1

這是我會做的。

# config/initializers/[anything].rb 
ActionView::Base.default_form_builder = CustomFormBuilder 

# lib/custom_form_builder.rb 
class CustomFormBuilder < ActionView::Helpers::FormBuilder 
    def label(field, text, options = {}) 
    if options[:hint] 
     hint = @template.content_tag(:span, options[:hint], :class => "hint") 
     super(field, "#{field.to_s.humanize} #{hint}", options) 
    else 
     super 
    end 
    end 
end