2009-02-26 64 views
29

我想盡可能方便地編輯表單域。例如,對於數字值,我希望字段以逗號(例如number_with_precision)顯示。如何格式化Rails編輯字段中顯示的值?

這在顯示器端很容易,但編輯怎麼樣?有沒有一個好的方法來做到這一點?

我正在使用Rails FormBuilder。經過調查,我發現它使用InstanceTag,它使用<attribute>_value_before_type_cast獲取字段的值,這意味着覆蓋<attribute>不會被調用。

+0

我已經開始在這個問題上的賞金,因爲我想知道如果有一個比JDL和我自己闡述的更好的答案。有它! – 2009-03-04 16:41:08

回答

37

我想出了迄今爲止最好的是這樣的:

<%= f.text_field :my_attribute, :value => number_with_precision(f.object.my_attribute) %> 

或者my_attribute可以返回格式化的值,就像這樣:

def my_attribute 
    ApplicationController.helpers.number_with_precision(read_attribute(:my_attribute)) 
end 

但你仍然必須使用:value

<%= f.text_field :my_attribute, :value => f.object.my_attribute %> 

這似乎很多工作。

+0

注意:如果您使用帶有逗號或貨幣符號格式的第一個解決方案,則需要將其排除在控制器的創建和更新方法中。 – LeBleu 2013-08-20 20:06:53

+0

我會避免使用第二種解決方案,在您的模型中引用`ApplicationController`對於養成習慣絕對不是好事。 – 2015-05-01 21:06:14

+0

最後一個對我來說最合適,我的功能仍然可以在我的數據模型中,並且不影響提交或編輯。好的解決方案 – 2016-09-29 15:34:52

9

我更喜歡你的第一個答案,格式是在視圖中完成的。但是,如果要在模型中執行格式設置,則可以爲getter和setter使用包裝器方法,並避免完全使用:value選項。

你最終會得到類似的東西。

def my_attribute_string 
    foo_formatter(myattribute) 
end 

def my_attribute_string=(s) 
    # Parse "s" or do whatever you need to with it, then set your real attribute. 
end 

<%= f.text_field :my_attribute_string %> 

Railscasts在episode #32的text_field中使用Time對象覆蓋了此事件。這個真正聰明的部分是他們如何處理驗證錯誤。單獨看這段情節是值得的。

3

如果您想要在編輯過程中創建或維護一種格式,您需要添加Javascript來實現「蒙版」。 Here is a demo.

這是第一次打these results

1

我做了類似的事情。我們使用自定義表單構建器來格式化時間和長度。它利用現有text_field的,但包裝它,因此該值可定製:

class SuperFormBuilder < ActionView::Helpers::FormBuilder 
    include ApplicationHelper 
    include FormHelper 
    include ActionView::Helpers::TagHelper 
    include ActionView::Helpers::FormTagHelper 

    def length_field(label,*args) 
    scale = 'medium' 
    args.each do |v| 
     if v.has_key?(:scale) 
     scale = v[:scale] 
     v.delete(:scale) 
     end 
    end 
    value = length_conversion(@object.send(label.to_sym),scale) 
    options = (args.length > 0) ? args.pop : {} 
    return has_error(label, text_field_tag(field_name(label),value,*args) + ' ' + length_unit(scale)) 
end 

private 
def field_name(label) 
    return @object_name + "[#{label}]" 
end 

def has_error(label, output) 
    return "<div class='fieldWithErrors'>#{output}</div>" if @object.errors[label] 
    return output 
end 

它用於這樣的:

<%= form_for(@section, {:action => 'save', :id => @section.id}, :builder => SuperFormBuilder) do |sf| %> 
    <%= sf.length_field :feed_size_min_w, :size => 3, :scale => 'small' %> 
<% end %> 

最終結果是基於在相應的單元中的值關閉他們在系統(公制,英制)上的選擇,並縮放IE小=英寸或毫米。

我基本上從現有的表單構建器中複製text_field方法,它使用text_field_tag本身。

有兩個問題:1)知道對象字段的名稱以及如何訪問對象以獲取要格式化的值。 2)獲取正確的名字,以便在提交表單時它是正確的參數散列的一部分。

表單構建器被賦予一個類變量@object。您可以使用.send方法獲取該字段的值。在我的情況下,我發送標籤:feed_size_min_w到@對象,並獲得其長度。然後將其轉換爲我想要的格式,並將其提供給text_field_tag。

該字段的名稱是使它最終在params散列中的關鍵,在我的實例中是params [:sections]之一。我做了一個叫做field_name的輔助函數來處理這個問題。

最後,如果該標籤上有錯誤,則has_error會將該字段包裝在錯誤div中。

3

您可以使用number_format插件。通過爲模型中的現有數字屬性指定number_format,該屬性現在將以所有格式和視圖的格式顯示爲Rails。在插入數據庫之前,它也將從該格式解析(當通過表單分配時)。 (該插件還創建了純數字unformatted_<attribute-name>存取方法可以繼續用於算術,或可無縫集成直接數值轉讓或獲取由你。)

class MyModel < ActiveRecord::Base 
    # this model has the balance attribute, which we 
    # want to display using formatting in views, 
    # although it is stored as a numeric in the database 
    number_format :balance, 
       :precision => 2, 
       :delimiter => ',', 
       :strip_trailing_zeros => false 

    def increment_balance 
    unformatted_balance += 10 
    end 

您還可以結合上面用JavaScript解決方案,這可以強制用戶在編輯時保持小數點和數千個分隔符,儘管這並不是必要的。

4

這是一個老問題,但萬一有人遇到這個問題,您可以使用number_to_X助手。他們有所有你所能想顯示你的編輯值的屬性:

<%= f.text_field :my_number, :value => number_to_human(f.object.my_number, :separator => '', :unit => '', :delimiter => '', :precision => 0) %> 

有更多的屬性可得:http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html

相關問題