【问题标题】:Is it possible to put just a rails form element in a partial?是否可以只在部分中放置一个rails表单元素?
【发布时间】:2010-10-17 23:10:37
【问题描述】:

我的应用有一个选择框供用户选择“地点”。如您所料,此选择框是一个表单。我在页面上的某处也有一个动作,它通过 AJAX 创建一个新的场地。创建新场地后,我想更新场地选择框以反映这一点。

我的解决方案是将选择框放在部分中,然后从控制器中的创建操作中呈现部分。

 <div id="venue_select" style="clear: both;">
    <%= render :partial => 'venue/venue_select_box' %>
 </div>

部分看起来像这样:

<%= f.collection_select :venue_id, @user_venues, :id, :name, :prompt => 'Select a venue' %>

其中 f 是表单引用:

<% form_for :shows do |f| %>

问题是 f 在部分中是未定义的,所以我得到一个错误。一种解决方案是包含整个表单,但我觉得这不是必需的,因为我没有更新整个表单。关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: ruby-on-rails ruby forms renderpartial partials


    【解决方案1】:

    我认为您的解决方案还不错,但是如果您尝试在另一种形式中使用此部分,则生成的字段名称会出现问题。

    为避免这种情况,您可以在 ajax 调用中提交 f.object_name 的内容。在您的情况下,它将是“shows”,因为方法是 :venue_id,所以生成的名称将是“shows[venue_id]”。

    【讨论】:

      【解决方案2】:

      这些都是不错的选择,但我认为我找到了最简单的。基本上,我只是在 collection_select 中硬编码了名称,所以我不需要“f”变量:

      <%= collection_select 'shows[venue_id]', :venue_id, @user_venues, :id, :name, { :prompt => 'Select one of your previous venues' } %>
      

      那么我的VenueController如下:

      class VenueController < ApplicationController
        layout 'main'
        before_filter :login_required, :get_user
      
        def create
          begin
            venue = @user.venues.create(params[:venue])
            @user_venues = @user.venues
            render :partial => 'venue_select_box', :success => true, :status => :ok
          rescue ActiveRecord::RecordInvalid => invalid
            flash[:errors] = invalid.record.errors
            render :text => '', :success => false, :status => :unprocessable_entity
          end
        end
      
      end
      

      如果由于任何原因这种方法是不好的做法,请告诉我,我很乐意为您提供答案。

      【讨论】:

        【解决方案3】:

        我同意 Sarah Mei 的观点,如果您的 AJAX 调用返回一个已添加场​​地的 JSON 表示,然后创建一个新选项并将其添加到选择元素中。

        一些用于添加选择选项的通用 JS 代码:

        var newOption = new Option("Text", "Value");
        selectElement.options[selectElement.options.length] = newOption;
        

        【讨论】:

          【解决方案4】:

          使用 Javascript 将场地添加到选择框可能更容易,作为 AJAX 添加上的 onComplete 挂钩。

          【讨论】:

            【解决方案5】:

            您可以像这样将变量传递给部分:

              <%= render :partial => 'venue/venue_select_box', :locals => { :f => f } %>
            

            对于这样的东西,看看documentation 总是好的。

            编辑:要使用带有 AJAX 请求的部分,您需要在 .rjs 模板中“重新创建”表单。因此,在您的控制器中,您需要再次找到该对象。

             def venue_select
                @venue = Venue.find(params[:id])
                respond_to do |format|
                  format.html
                  format.js
                end
             end
            

            然后在你的场地/venue_select.rjs 文件中:

             form_for @venue do |f|
               page[:element].replace_html :partial => 'venue/venue_select_box', :locals => { :f => f }
             end
            

            其中:element 是您要替换的选择菜单的ID。 基本上,您只需重新创建 form_for,然后使用它来更新选择字段。

            【讨论】:

            • 这在视图中有效,但我也需要从控制器进行渲染。选择框提取可以通过 AJAX 更新的数据,因此更新请求将告诉控制器再次呈现部分......然后“f”再次未定义
            • 啊,抱歉,我没有在您的问题中看到 AJAX 需求。下次我可能应该更仔细地阅读......我刚刚更新了我的答案,可能会对您有所帮助。
            • 您将如何使用 Rails 3/4 和 UJS 做到这一点?我遇到的问题是,如果不将 form_for 放在打印标签中,您将无法获取表单的任何部分,然后打印整个表单。
            猜你喜欢
            • 2016-07-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-02-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多