【问题标题】:How do I render a partial containing a form_for for an edit function?如何为编辑功能渲染包含 form_for 的部分?
【发布时间】:2017-03-04 01:41:45
【问题描述】:

我在父视图中有一个div,它呈现一个show 部分。在这个show 部分中,我有一个按钮应该更改父部分的部分以呈现“表单”部分以编辑对象,但我一直卡住,因为似乎“表单”部分的form_for 缺少@project 对象。

如何将此对象传递给“表单”部分?我还缺少其他东西吗?

我对使用 AJAX 比较陌生。如果您需要,很乐意提供更多信息。

我在服务器终端中遇到的错误是

ActionView::Template::Error (First argument in form cannot contain nil or be empty):

routes.rb

    get 'switchProjectView', to: 'projects#switch_main_view'
    resources :projects

projects_controller.rb

class ProjectsController < ApplicationController

  def new
    @project = Project.new
  end

  def create
    @project = Project.new(project_params)
    if @project.save
      flash[:success] = "New Project Added"
      redirect_to @project 
    else
      flash[:danger] = "Project Not Added. Please Try Again"
    end

  end

  def show
    @project = Project.find(params[:id])
  end

  def index
    @projects = Project.all
  end

  def update 
    @project = Project.find(params[:id])
    if @project.update_attributes(project_params)
      redirect_to @project
    else
      render 'edit'
    end
  end

  def edit

  end

  def switch_main_view
    respond_to do |format|               
      format.html
      format.js
    end    
  end     


  def project_params
    params.require(:project).permit(:main_contact_name, :id, :main_contact_phone, :main_contact_email, :project_name)
  end

end

show.html.erb

    <div class="body">
      <div class="center jumbotron heading-jumbo">
        <h1><%= @project.project_name %></h1>  
      </div>

      <div class="body-jumbo jumbotron" id='project-details'>
        <%= render "projects/show" %>
      </div>
    </div>

switch_main_view.js.erb

    $('#project-details').html("<%= j render :partial => 'projects/form' %>");

_form.html.erb

  <%= form_for(@project) do |f| %>

      <%= f.label :project_name %>
      <%= f.text_field :project_name, class: 'form-control'%>

      <%= f.label :main_contact_name %>
      <%= f.text_field :main_contact_name, class: 'form-control'%>

      <%= f.label :main_contact_phone %>
      <%= f.text_field :main_contact_phone, class: 'form-control'%>

      <%= f.label :main_contact_email %>
      <%= f.text_field :main_contact_email, class: 'form-control'%>

      <%= f.submit 'Save Project', class: 'btn btn-primary'%>

  <% end %>

_show.html.erb

<div class='text-center center'>
    <h3><strong>Project Information</strong></h2>  
</div>
<h2>Start Date: Launch Date:</h1>
<span class='pull-right jumbo-btn-span'><%= link_to "Edit Project Information", switchProjectView_path(@project), remote: true, class:'btn btn-primary jumbo-btn' %></span>
<h2>Primary Conact's Name:  <%= @project.main_contact_name %></h2>
<h2>Primary Conact's Phone: <%= @project.main_contact_phone %></h2>
<h2>Primary Conact's Email: <%= @project.main_contact_email %></h2>

【问题讨论】:

  • 你在主视图的控制器中声明了@project吗?
  • 是的,我有。父 show.html.erb 上的项目/显示部分正确显示 @project 数据
  • 问题是 ruby​​ 变量随页面一起呈现,当您添加部分时,浏览器不会调用它。如果它已经声明了,你有没有想过只是隐藏 div 而是将它与页面一起加载,然后在需要时显示它,而不是稍后添加 html?
  • 这是有道理的,这当然是一种选择。有没有办法通过js文件和link_to将变量传递给partial?
  • 通过ajax可以。声明服务器变量,然后加载页面。因此,通过附加 .html,您将跳过第一部分并仅附加 html。即使您可以继续使用它们似乎是合理的,因为它们是“服务器变量”,浏览器不能只是继续操纵它们。如果您考虑错误:@project.something = nil。没有 ping 服务器以获取该项目记录,以查看 .something 是什么。

标签: javascript jquery ruby-on-rails ajax


【解决方案1】:

好吧,对于每个请求,您都需要在控制器方法中重新初始化变量。在您的情况下,您需要执行以下操作:

def switch_main_view
  @project = Project.new
  respond_to do |format|               
    format.html
    format.js
  end    
end

这样做将使您摆脱错误:表单中的第一个参数不能包含 nil 或为空,但这不会使您能够执行您实际尝试执行的操作。

当你使用link_to 时,默认情况下它会发送一个 HTML 请求,正如你在 Rails 日志中看到的那样,会出现如下内容:

Processing by ProjectsController#switch_main_view as HTML

为了获得 JS 响应,您需要告诉 link_to 您准备接受 JS 响应,而不是 HTML 响应,您可以通过在 link_to 中传递 format: :js 来做到这一点:

<%= link_to "Edit Project Information", switchProjectView_path(@project, format: :js), remote: true, class:'btn btn-primary jumbo-btn' %></span>

remote: true 将确保您没有重新加载页面内容,而是尝试在后台从服务器获取内容。

【讨论】:

    【解决方案2】:

    您的请求“switchProjectView_path(@project)”仅将对象 ID 发送到服务器,因此您需要加载对象以将其呈现在视图中以供响应。
    1. 首先路由应该是这样的,这样,url 可以包含对象 id:
    get 'switchProjectView/:id', to: 'projects#switch_main_view', as:"switchProjectView"
    2.您必须在控制器中加载对象: def switch_main_view @project = Project.find(params[:id]) respond_to do |format| format.html format.js end end

    【讨论】:

    • 这最终成功了。我能够使用 params / controller 方法渲染查找和渲染 @project 对象。谢谢
    【解决方案3】:

    在调用部分时尝试传递变量:

    $('#project-details').html("<%= j render :partial => 'projects/form', locals: {project: @project} %>");
    

    【讨论】:

    • 仍然没有 :-( FWIW,当其中没有变量时,部分呈现。
    猜你喜欢
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多