【问题标题】:Multiple forms for the same model in a single page在一个页面中为同一模型提供多个表单
【发布时间】:2010-02-06 21:39:27
【问题描述】:

在我的rap lyrics explanation site的首页,有一个地方可以让用户尝试解释一个具有挑战性的行:

alt text http://dl.dropbox.com/u/2792776/screenshots/2010-02-06_1620.png

这是我用来生成这个的部分:

<div class="stand_alone annotation" data-id="<%= annotation.id %>">
  <%= song_link(annotation.song, :class => :title) %>

  <span class="needs_exegesis"><%= annotation.referent.strip.gsub(/\n/, "\n <br />") %></span>

  <% form_for Feedback.new(:annotation_id => annotation.id, :created_by_id => current_user.try(:id), :email_address => current_user.try(:email)), :url => feedback_index_path, :live_validations => true do |f| %>
    <%= f.hidden_field :annotation_id %>
    <%= f.hidden_field :created_by_id %>
    <p style="margin-top: 1em">
        <%= f.text_area :body, :rows => 4, :style => 'width:96%', :example_text => "Enter your explanation" %>
    </p>
    <p>
      <% if current_user %>
        <%= f.hidden_field :email_address %>
      <% else %>
        <%= f.text_field :email_address, :example_text => "Your email address" %>
      <% end %>
      <%= f.submit "Submit", :class => :button, :style => 'margin-left: .1em;' %>
    </p>
  <% end %>
</div>

但是,在单个页面上放置多个这些是有问题的,因为 Rails 会自动为每个表单分配一个 ID new_feedback,并为每个字段分配一个类似 feedback_body 的 ID(导致名称冲突)

显然我可以在表单及其所有字段中添加类似:id =&gt; '' 的内容,但这似乎有点重复。最好的方法是什么?

【问题讨论】:

    标签: ruby-on-rails ruby forms


    【解决方案1】:

    如果您不想更改输入名称或模型结构,可以使用 id 选项使您的表单 ID 唯一,并使用 namespace 选项使您的输入 ID 唯一:

    <%= form_for Feedback.new(...), 
        id: "annotation_#{annotation.id}_feedback"
        namespace: "annotation_#{annotation.id}" do |f| %>
    

    这样我们的表单 ID 是唯一的,即annotation_2_feedback,这也会添加一个前缀,例如annotation_2_,用于通过f 创建的每个输入。

    【讨论】:

      【解决方案2】:

      您是否考虑过用于 rails 模型的nested_attributes?您可以拥有多个edit 注释表单,其中每个注释都包含新反馈的字段,而不是拥有多个new 反馈表单,每个表单都与一个注释相关联。生成表单的 id 将包括注释 id,例如 edit_annotation_16

      注释模型将与其反馈有关系,并且还将接受它们的嵌套属性。

      class Annotation < ActiveRecord::Base
        has_many :feedbacks
        accepts_nested_attributes_for :feedbacks
      end
      
      class Feedback < ActiveRecord::Base
        belongs_to :annotation
      end
      

      然后,您可以根据需要添加任意数量的表单,每个注释一个。例如,这是我尝试过的:

      <% form_for @a do |form| %>
          Lyrics: <br />
          <%= form.text_field :lyrics %><br />
          <% form.fields_for :feedbacks do |feedback| %>
              Feedback: <br/>
              <%= feedback.text_field :response %><br />
          <% end %>
          <%= form.submit "Submit" %>
      <% end %>
      
      <% form_for @b do |form| %>
          Lyrics: <br />
          <%= form.text_field :lyrics %><br />
          <% form.fields_for :feedbacks do |feedback| %>
              Feedback: <br/>
              <%= feedback.text_field :response %><br />
          <% end %>
          <%= form.submit "Submit" %>
      <% end %>
      

      以及上述编辑视图的快速而肮脏的控制器:

      class AnnotationsController < ApplicationController
        def edit
          @a = Annotation.find(1)
          @a.feedbacks.build
          @b = Annotation.find(2)
          @b.feedbacks.build
        end
      
        def update
          @annotation = Annotation.find(params[:id])
          @annotation.update_attributes(params[:annotation])
          @annotation.save!
          render :index
        end
      end
      

      【讨论】:

        【解决方案3】:

        我在我目前正在开发的网站上遇到了同样的问题,并采用了您在底部提到的解决方案。如果您以编程方式生成 ID 并将整个表单放在一个部分中,这不是重复的。例如,在我的网站上,我每页有多个“条目”,每个条目都有两个投票表格,一个投票赞成,一个投票反对。每个条目的记录 ID 都附加到其投票表单的 DOM ID 中,以使其唯一,如下所示(仅显示投票按钮,投票按钮类似):

        <% form_for [entry, Vote.new], :html => { :id => 'new_up_vote_' + entry.id.to_s } do |f| -%>
          <%= f.hidden_field :up_vote, :value => 1, :id => 'vote_up_vote_' + entry.id.to_s %>
          <%= image_submit_tag('/images/icon_vote_up.png', :id => 'vote_up_vote_submit' + entry.id.to_s, :class => 'vote-button vote-up-button') %>
        <% end -%>
        

        【讨论】:

          【解决方案4】:

          我也遇到了同样的问题,但我想要一个比在每个字段中添加 ID 更具可扩展性的解决方案。因为我们已经在使用 form_for ... |f|诀窍是更改模型的名称并获得一个新的 HTML ID 前缀。

          使用此方法的变体:http://www.dzone.com/snippets/create-classes-runtime(我删除了 &block 的东西)

          我创建了一个新模型,它是我想要在同一页面上创建第二个表单的模型的精确副本。然后使用该新模型来呈现新表单。

          如果第一个表单正在使用

          @address = Address.new
          

          然后

          create_class('AddressNew', Address)
          @address_new = AddressNew.new
          

          对于同一型号的第二种形式,您的 ID 前缀将是“address_new_”而不是“address_”。当您阅读表单参数时,您可以创建一个地址模型来将值放入。

          【讨论】:

            【解决方案5】:

            对于那些在这里绊倒,正在寻找 Rails 3.2 应用程序的解决方案的人,请查看以下问题:

            Rails: Using form_for multiple times (DOM ids)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-02-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多