【问题标题】:Passing local variable issue传递局部变量问题
【发布时间】:2014-08-06 23:11:38
【问题描述】:

您好,我有一个 rails 4 应用程序,其中有以下代码:

<%= form_for @store, do |f| %>
  <%= f.fields_for :products do |builder| %>
    <%= render "product_fields",  f: builder %>
  <% end %>
  <%= link_to_add_fields "Add Product", f, :products  %>
<% end %>

然后我有 _product_fields.html.erb 喜欢:

<%= f.select :type_of, %w[Blah blah], {}, class: "select_it" %>
<div class='product-view'>
   <%= render "stores/product_form/bookshelf", f:f %>
</div>

我的 javascript(coffeescript) 看起来像:

$('form').on 'change', '.select_it', (e) ->
   value = $(this).val()
   params = 'type=' + value
   $.ajax({
     url: "/switch_product",
     data: params
   })

然后我的控制器看起来像:

def switch_product
  @type = params[:type]
  respond_to do |format|
    format.js
  end
end

然后我有一个 switch_product.js.erb 文件,如下所示:

$(this).(".product-view").html("<%= j render "stores/product_form/#{@type.downcase}", f:f %> ");

但是在 switch_product.js.erb 上我得到了错误:

undefined local variable or method `f'

如何将局部变量从页面传递到 js.erb 文件?

编辑:

这是我尝试使用 switch_product.js.erb 呈现的内容(但这只是一个,我也有 _books.html.erb 和 _bookshelf.html.erb:

<%= f.hidden_field :the_type_is, value: "Birdhouse" %>
  <%= f.fields_for :product_fields, f.object.product_fields.build do |builder| %>
  <%= builder.text_area :price %>
<% end %>

【问题讨论】:

  • 试试这个$(this).(".product-view").html("&lt;%= j render "stores/product_form/#{@type.downcase}", :locals =&gt; { :f =&gt; f } %&gt;");
  • @Pavan,好的,我试过了,但还是出现同样的错误?
  • 您在哪一行得到错误?
  • @Pavan,我已经启动了 Chrome 开发人员工具,并且在 switch_product.js.erb 的网络页面上,整个文件(只是我发布的行)被错误输出了
  • 我猜这个".product-view"应该是"#product-view"

标签: javascript jquery ruby-on-rails ruby coffeescript


【解决方案1】:

您的错误来自您的 .js.erg:

  <%= j render "stores/product_form/#{@type.downcase}", f:f %>

最后的f:f。你想在那里做什么?

【讨论】:

  • 我正在尝试将局部变量传递给呈现的部分
  • 我也尝试过使用locals: { f:f },但这也不起作用。
  • 问题是f 没有在你引用它的上下文中定义。您正在尝试使用单个键/值传递散列,键是符号:f,值是变量f。但是没有定义变量f。那是你想要做的吗?您希望变量f 被定义为什么,它是在哪里定义的?
  • 它在 product_fields.html.erb 中定义,在 _form.html.erb 中呈现为部分。当我单击 _product_fields.html.erb 上的选择时,我希望它将 f 传递给 .js.erb 页面
【解决方案2】:

看起来switch_product.js.erb 是从与上述文件不同的控制器操作呈现的。如果是这种情况,这将不起作用。您在第一个操作中的 HTML 渲染期间实例化了一个构建器,一旦完成渲染该页面,构建器就超出了范围并被传递给 Ruby 垃圾收集器。

您需要重新渲染整个表单,一直到第一个文件中的 &lt;%= form_for @store, do |f| %&gt; 内容。您没有提供该文件的文件名,所以假设它是 show.html.erb

我要做的基本上是将所有这些移至_product_form.html.erb(除非它已经是部分的),然后更改switch_product.js.erb 以呈现该部分:

$(this).(".product-view").html("<%= j render(partial: 'product_form') %>");

假设整个表单最初位于.product-view 下,它将替换您的整个表单。可能会有一些特定于您的应用的更详细的工作,但这应该会让您朝着正确的方向前进。

【讨论】:

  • 对不起,我没有真正关注你。所以你在product_fields.html.erb中的说法,我应该将form_for(它最初在我的new.html.erb文件中)调用移动到它?
  • 好的,我会将 form_for 从 new.html.erb 中移出,移到名为 _product_form.html.erb 的部分中。然后 new.html.erb 只会渲染(部分:'product_form'),而 switch.js.erb 会做我上面发布的。
【解决方案3】:

问题是您试图在您的 js.erb 文件的部分中传递 表单构建器。你不能这样做。当您通过 ajax 调用提交表单时,控件将移至控制器内的 ajax 方法,并且表单构建器的范围也已完成

如果您查看 js.erb 文件中的代码:

$(this).(".product-view").html("<%= j render "stores/product_form/#{@type.downcase}", f:f %> ");

有两个问题:

一个。 this 关键字失去了作用域,所以你不能在这里使用它。要修复此问题,您需要指定该元素的 id 或类

b.您的表单构建器f 也失去了作用域,因此您需要渲染整个表单本身,而不是渲染表单的一部分

而不是渲染这部分

<%= f.hidden_field :the_type_is, value: "Birdhouse" %>
<%= f.fields_for :product_fields, f.object.product_fields.build do |builder| %>
  <%= builder.text_area :price %>
<% end %>

你需要渲染这个:

<%= form_for @store, do |f| %>
  <%= f.fields_for :products do |builder| %>
    <%= render "product_fields",  f: builder %>
  <% end %>
  <%= link_to_add_fields "Add Product", f, :products  %>
<% end %>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 2011-09-10
    • 2015-09-27
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多