【问题标题】:How can I format the value shown in a Rails edit field?如何格式化 Rails 编辑字段中显示的值?
【发布时间】:2009-02-26 18:59:27
【问题描述】:

我想让编辑表单字段尽可能方便用户。例如,对于数值,我希望该字段以逗号显示(如number_with_precision)。

这在显示方面很容易,但是编辑呢?有什么好办法吗?

我正在使用 Rails FormBuilder。经过调查,我发现它使用了InstanceTag,它通过使用<attribute>_value_before_type_cast获取字段的值,这意味着覆盖<attribute>不会被调用。

【问题讨论】:

  • 我已经开始对这个问题进行赏金,因为我想知道是否有比 JDL 和我自己提出的更好的答案。试试吧!

标签: ruby-on-rails ruby forms


【解决方案1】:

到目前为止我想出的最好的是这样的:

<%= 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 %>

这似乎需要做很多工作。

【讨论】:

  • 注意:如果您使用第一个解决方案的格式添加了逗号或货币符号,则需要在控制器的创建和更新方法中将它们去掉。
  • 我会避免使用第二种解决方案,从你的模型中引用ApplicationController 绝对不是养成这样做的好习惯。
  • 最后一个对我来说效果最好,我的函数仍然可以在我的数据模型中并且不影响提交或编辑。不错的解决方案!
【解决方案2】:

我更喜欢你的第一个答案,格式是在视图中完成的。但是,如果您想在模型中执行格式化,您可以对 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】:

    这是一个老问题,但如果有人遇到这个问题,您可以使用 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

    【讨论】:

      【解决方案4】:

      如果您希望在编辑期间创建或维护格式,则需要添加 Javascript 来实现“掩码”。 Here is a demo.

      这是these results中的第一个热门。

      【讨论】:

      【解决方案5】:

      您可以使用number_format 插件。通过为模型中的现有数字属性指定number_format,该属性现在将在所有表单和视图中显示为 Rails 格式。在插入数据库之前,它还将从该格式(通过表单分配时)解析回来。 (该插件还创建纯数字 unformatted_&lt;attribute-name&gt; 访问器,可以继续用于算术,或直接用于数字分配或检索以实现无缝集成。)

      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 解决方案结合使用,这可以强制用户在编辑时保留小数点和千位分隔符,尽管这实际上没有必要。

      【讨论】:

        【解决方案6】:

        我做过类似的事情。我们使用自定义表单构建器格式化时间和长度。它利用现有的 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 small = 英寸或毫米的选择,采用适当单位的值。

        我基本上从现有的表单构建器中复制了 text_field 方法,它使用了 text_field_tag 本身。

        有两个陷阱:1)知道对象字段的名称以及如何访问对象以获取要格式化的值。 2) 获取正确的名称,以便在提交表单时它是正确参数哈希的一部分。

        表单生成器被赋予一个类变量@object。您可以使用 .send 方法获取字段的值。在我的情况下,我将标签 :feed_size_min_w 发送到 @object 并取回它的长度。然后我将其转换为我想要的格式,并将其提供给 text_field_tag。

        字段的名称是让它最终出现在 params 哈希中的关键,在我的例子中是 params[:sections] 之一。我创建了一个名为 field_name 的小辅助函数来处理这个问题。

        最后,如果标签上有错误,has_error 会将字段包装在错误 div 中。

        【讨论】:

          【解决方案7】:

          我需要一些指定文本字段的“更好”格式,通过将其添加到我的初始化程序来解决它。似乎在 Rails ~= 5.2 上运行良好,而且应该很容易定制。

          class ActionView::Helpers::Tags::TextField
            private
          
            def value_before_type_cast  # override method in ActionView::Helpers::Tags::Base
              v = super
          
              # format as you like, when you like
              if @options.delete(:nice_decimal)
                v = v.to_s.gsub('.', ',') if v.is_a?(BigDecimal)
              end
          
              v
            end
          end
          

          f表格中使用

          <%= f.text_field :foo, nice_decimal: true %>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-09-24
            • 2011-08-26
            • 2010-11-03
            • 2020-08-14
            • 2020-12-17
            • 1970-01-01
            相关资源
            最近更新 更多