【问题标题】:Custom form helpers自定义表单助手
【发布时间】:2011-02-07 01:43:03
【问题描述】:

有没有一种方法可以让我创建一个自定义表单助手,以便代替:

special_field_tag :object, :method

我可以达到这样的效果:

form.special_field :method

【问题讨论】:

    标签: ruby-on-rails ruby forms helpers


    【解决方案1】:

    是的,您可以添加到 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 - 对象的类名
    • @template - 我认为它是 ActionView 的一个实例,您可以通过调用模板上的方法绕过我添加的所有包含。还没试过。
    • @options - 由 form_for 调用创建时传递给 FormBuilder 的选项

    我编写了 field_id 和 field_name 方法来在 HTML 输入元素上创建这些属性,就像常规助手所做的那样,我确信有一种方法可以与 Rails 使用的相同方法联系起来,但我还没有还没找到呢。

    使用这些辅助方法可以做的事情没有限制,它们只是返回字符串。您可以在一个页面中创建整个 HTML 表格或页面,但您最好有充分的理由这样做。

    此文件应添加到 app/helpers 文件夹中

    【讨论】:

    • 您也可以继承 FormBuilder,然后根据每个表单使用您的自定义构建器: MyFormBuilder do |f| %> ...
    • 或全局,ActionView::Base.default_form_builder = MyFormBuilder
    • 你把这个文件放在哪里?你会拒绝上课吗?
    • @jalcine /app/helpers/ 似乎是标准的。
    • 这个好像没有自动收录,怎么收录?
    【解决方案2】:

    @Tilendor,非常感谢您的指点。下面是一个 enum_select 表单标签助手的示例,它使用 Rails 4.1 枚举自动填充选择标签的选项:

    # 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 />
    

    【讨论】:

      【解决方案3】:

      我们的应用在文本字段中显示电话号码,我们希望省略国内号码的国家/地区代码。我正在使用表单助手。在阅读了this和rails source之后,我来到了这个解决方案:

      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
      

      我把它放在 app/helpers/application_helper.rb 上并像使用 text_field() helper 一样使用它。希望这对某人有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-07
        • 1970-01-01
        • 1970-01-01
        • 2014-09-03
        • 1970-01-01
        • 2014-02-08
        • 1970-01-01
        • 2017-08-08
        相关资源
        最近更新 更多