自定义表单助手

发布于 2024-08-28 17:46:40 字数 162 浏览 7 评论 0原文

有没有一种方法可以创建自定义表单助手,这样

special_field_tag :object, :method

我就可以实现以下目标:

form.special_field :method

Is there a way that I can create a custom form helper so that instead of:

special_field_tag :object, :method

I can achieve something like:

form.special_field :method

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一世旳自豪 2024-09-04 17:46:40

是的,您可以添加到 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 文件夹中

Yes, you can add to the FormBuilder class and get access to the object passed into the form_for. I've done this for a lot of things: dates, times, measurements, etc. Heres an example:

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

Which you can use like this:

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

There are some instance variables created by Rails that you can access in these helper methods:

  • @object - the model object specified by the form
  • @object_name - the class name of the object
  • @template - I think its an instance of the ActionView, you can possibly bypass all the includes I added by calling methods on the template. Haven't tried that yet.
  • @options - options passed to the FormBuilder when its created by the form_for call

I wrote the field_id and field_name methods to create these attributes on the HTML input elements the same way the regular helpers do, I'm sure there is a way to tie into the same methods that Rails uses, but I haven't found it yet.

The sky is the limit on what you can do with these helper methods, they simply return strings. You can create entire HTML tables or pages in one, but you better have a good reason to.

This file should be added in the app/helpers folder

冷…雨湿花 2024-09-04 17:46:40

@Tilendor,非常感谢您的指点。下面是一个 enum_select 表单标签助手的示例,它使用 Rails 4.1 枚举自动填充 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 />

@Tilendor, thanks so much for the pointers. Here is an example of an enum_select form tag helper that uses Rails 4.1 enums to automatically populate the options of a select tag:

# 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

The trickiest construct is @object.class.send(name.to_s.pluralize) which produces a hash of available values (e.g., Company.time_zones). Putting it in helpers/application_helper.rb makes it automatically available. It is used like:

<%= f.label :billing_status %>:
<%= f.enum_select :billing_status %><br />
一笑百媚生 2024-09-04 17:46:40

我们的应用程序在文本字段中显示电话号码,我们想省略国内号码的国家/地区代码。我正在使用表单助手。在阅读了这篇文章和 Rails 源代码之后,我找到了这个解决方案:

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() 帮助器一样使用它。希望这对某人有帮助。

Our app was displaying phone numbers in text fields, and we wanted to omit the country code for domestic numbers. I was using form helpers. After reading this and rails source a bit, i came to this solution:

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

I put this on app/helpers/application_helper.rb and use it like i use text_field() helper. Hope this helps someone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文