在 f.label 中嵌套输入(rails form generation)

Posted

技术标签:

【中文标题】在 f.label 中嵌套输入(rails form generation)【英文标题】:Nest input inside f.label ( rails form generation ) 【发布时间】:2011-01-28 06:26:00 【问题描述】:

我想使用 f.label 方法来创建我的表单元素标签,但是 - 我想让表单元素嵌套在标签内。这可能吗?

-- 来自 W3C--

要将标签与另一个控件隐式关联,控件元素必须在 LABEL 元素的内容内。在这种情况下,标签可能只包含一个控制元素。标签本身可以位于关联控件之前或之后。

在这个例子中,我们隐式地将两个标签与两个文本输入控件关联起来:

<form action="..." method="post">
 <p>
  <label>
     First Name
     <input type="text" name="firstname" />
  </label>
  <label>
     <input type="text" name="lastname" />
     Last Name
  </label>
  </p>
</form>

【问题讨论】:

【参考方案1】:

正如前面提到的 Dan Garland,您绝对可以使用简单的块将输入嵌套在标签内。我提供这个答案作为使用 ERB 的示例,特别是为了准确说明您必须如何获得Bootstrap button groups to work like radio buttons,因为它们需要这种嵌套。我花了一段时间才弄清楚,所以希望这对其他人有帮助。

对于此示例(Rails 4.2),按钮组允许用户在 3 个不同的距离选项之间进行选择:

<%= form_for(@location) do |f| %>
  <div class="field form-group">
    <%= f.label :distance %><br>
    <div class="btn-group" data-toggle="buttons">
      <%= f.label :distance, class: "btn btn-primary active" do %>
        <%= f.radio_button :distance, 0.3, checked: true %>
        0.3 miles
      <% end %>
      <%= f.label :distance, class: "btn btn-primary" do %>
        <%= f.radio_button :distance, 0.5 %>
        0.5 miles
      <% end %>
      <%= f.label :distance, class: "btn btn-primary" do %>
        <%= f.radio_button :distance, 1 %>
        1 mile
      <% end %>
    </div>
  </div>
  <div class="actions">
    <%= f.submit "Submit Location", class: "btn btn-success" %>
  </div>
<% end %>

附:我还不能发布屏幕截图来展示它的样子,但是一旦我获得足够的代表点数,我会的。

【讨论】:

【参考方案2】:

您可以使用块将表单助手嵌套在标签内。这是一个使用 HAML 的示例,但它也适用于 ERB。

= form_for your_resource do |f|
  = f.label :first_name do
    = f.text_field :first_name

【讨论】:

适用于没有 HAML(普通 erb)的 Rails 3 (3.2.9)。 谢谢!在没有haml的rails 4.0.4中工作。【参考方案3】:

使用这个小解决方法

<%= f.label(:content, "#f.check_box(:allow_posts)\n#:content\n".html_safe, :class => "checkbox") %>

会给你这个

<label class="checkbox" for="pages_content"><input name="pages[allow_posts]" type="hidden" value="0"><input id="pages_allow_posts" name="pages[allow_posts]" type="checkbox" value="1">

内容

【讨论】:

对不起,我以为这是在询问复选框是否包含在标签标签中【参考方案4】:

您可以使用自定义 FormBuilder 来允许标签助手接受块。就这么简单:

class SmartLabelFormBuilder < ActionView::Helpers::FormBuilder
  def label(method, content_or_options_with_block = nil, options = , &block)
    if !block_given?
      super(method, content_or_options_with_block, options)
    else
      options = content_or_options_with_block.is_a?(Hash) ? content_or_options_with_block.stringify_keys : 

      @template.content_tag(:label, options, &block)
    end
  end
end

然后你可以像这样使用你的表单生成器:

<% form_for(@article, :builder => SmartLabelFormBuilder) do |form| %>
  <% form.label(:title) do %>
    Title
    <%= form.text_field(:title) %>
  <% end %>
<% end %>

【讨论】:

包装得很好,但它没有输出 for 属性,据我所知,普通助手会这样做。也就是说,当我说&lt;% form.label(:title) %&gt; 时,它会输出&lt;label for="title"&gt;,但是当我添加块时,无论我做什么,它都只会输出&lt;label&gt;。我做错了吗? @BenSaufley:标签包裹输入元素时,不需要 for 属性。 w3.org/TR/html401/interact/forms.html#h-17.9.1【参考方案5】:

使用内置的 Rails 的 labellabel_tag 助手是不可能的,因为它们不占用块。但是,如果你想要嵌套,那为什么不直接使用 HTML 元素呢?—

<label>
  <%= f.text_field :firstname %>
</label>

【讨论】:

只是因为我想利用rails标签的自动化 Rails 的助手将输入元素的 ID 属性的值分配给标签元素的 for 属性。它不是特别复杂。无论是使用 Rails 的帮助器还是在标签内嵌套输入元素,效果都是一样的;在浏览器中单击标签会将焦点设置到输入元素。 这让我觉得是 Rails 中的一个巨大疏忽,我真的很惊讶这个问题没有得到解决。至少我们有像 Tim Riley 这样的人来帮助我们解决问题。 我使用的是旧版本的 Rails。这对我来说很有效,因为有时“帮助者”会妨碍你,编写你想要/需要的 HTML 代码更容易,而不是试图强迫 Rails 让你做你想做的事。

以上是关于在 f.label 中嵌套输入(rails form generation)的主要内容,如果未能解决你的问题,请参考以下文章

Rails cocoon嵌套字段,在编辑表单上呈现每个字段旁边的现有图像

验证 rails 输入字段是不是为数字。

在rails中使用accepts_nested_attributes_for的三层嵌套表单

在rails应用程序中使用Ransack搜索表单中的关联多对多关联

Rails fields_for 表单未显示,嵌套表单

rails f.number_field vs number_field_tag