如何在JS视图中将JavaScript变量传递到Erb代码中?

29

我在我的Rails 3项目中有这个Javascript视图:

app/views/expenses/new_daily.js.erb

var i = parseInt($('#daily').attr('data-num')) + 1;
//$('#daily').append('agrego fila ' + i + ' <br />');

$('#daily').append('<%= escape_javascript(render(partial: 'new_expense', locals: { i: i })) %>');

$('#daily').attr('data-num', i);
我想通过locals将我的' i 'javascript变量传递到一个ruby部分中,我该如何实现这个?
8个回答

23
据我所知,没有直接完成这个任务的方法,原因很简单:HTML在服务器端执行,而JavaScript是客户端语言,也就是在本地浏览器中执行,这意味着如果您想在两者之间传递变量,您将不得不向服务器发出请求。
然而,通过调用AJAX请求来解决这个问题,这个AJAX请求与发送新的请求给服务器执行相同的功能,但是它不会刷新或重新加载页面,从而使用户产生没有请求的错觉。
一个人提出了类似的问题,可以在这里看到。
你可以在MDN上了解更多关于AJAX的内容。

9
对于这个回答点一个赞,但是对于指向w3schools点一个踩。每个网页开发者都应该知道w3schools很糟糕,可以看一下w3fools来了解原因。应该使用Mozilla开发者中心的文档。 - marco-fiset
3
FYI,HTML 不是在服务器端执行的,而是 ERB。ERB 是用于生成 HTML 的模板语言。然后将 HTML 发送到客户端并由客户端呈现。 - Ajedi32

16

您可以使用jQuery传递值。

<%=f.text_field :email ,:id=>"email_field" %>

<script type="text/javascript">
   var my_email= "my@email.com"
   $(document).ready(function(){
        $("#email_field").val(my_email);
   });
</script>

1
好的。现在假设表单生成器 f. 正在建模 :user,点击提交按钮将会把 "my@email.com" 通过 params[:user][:email] 发送给 Rails。完美,这正是我想要的。 - Arta
10
问题是如何将JavaScript中的值传递到在Rails不显眼JavaScript控制器操作响应(js.erb文件)中呈现的Ruby ERB部分。本答案描述了如何使用JavaScript设置表单字段的值。因此,尽管获得了最多的赞成票,但这不是问题的答案。 - user3670743
大家好,除了属性之外,你们能否也传递object.id?我正在使用fullcalendar和bootstrap modal在事件控制器的索引操作中,当窗口弹出时,我可以使用fullcalendar预先设置字段的表单属性值(因此我不需要在控制器中使用params[:id]提前查找对象)。我想将其提交为rails表单的原因是为了进行服务器端验证。你能告诉我如何将id传递给form_for助手以更新给定的对象,以及我的控制器索引操作将如何处理@event对象? - Sean Magyar

3
简单的回答是你不能。部分视图在服务器端展开,而JavaScript变量是后来在客户端设置的。你可以将(作为变量名)作为部分的参数,并在那里使用它。
render :partial => 'xx', :locals => { :variable => 'i' }

在部分情况下

alert(<%= variable %>);

5
为什么你说你不能传递一个变量,但是又提供了一个与该语句相矛盾的例子,在这个例子中,你实际上通过JS将i的内容传递到客户端以进行警报? - Sam Figueroa

3

1) 您可以在erb模板中创建一个带有全局变量的js标签,之后您将能够从任何js文件中访问该变量。

<%= javascript_tag do %>
   window.productsURL = '<%= j products_url %>';
<% end %>

2) 你可以在erb模板中传递数据到data属性,然后通过客户端的js访问它,如下所示:$('#products').data('products')

<%= content_tag "div", id: "products", data: {products: Product.limit(10)} do %>
   Loading products...
<% end %>

3) 您可以使用gon将Rails变量用于您的js中。

这里有一篇很好的文章,阅读它并找到适合您特定情况的解决方案:http://railscasts.com/episodes/324-passing-data-to-javascript, 更多评论请参见此处:http://railscasts.com/episodes/324-passing-data-to-javascript?view=asciicast


感谢指向javascript_tag的指针。标签内的eval函数以非常简单的方式解决了问题。我猜SO用户会将其投票否决,因为这更像是模板而不是在运行时“传递”。但是,如果您可以在呈现页面时从erb中直接将数据写入DOM,为什么要使用AJAX呢? :) - count0

3

2

1
欢迎来到 Stack Overflow,通常我们避免将单个链接作为答案发布,能否简要概括一下它的内容? - Sam Saffron

2

这里其他最好的答案都是正确的,无法通过将javascript变量传递到erb局部模板中来实现,因为它是在服务器上呈现的,而不是在客户端。

但是,由于任何寻找此解决方案的人可能都对解决方法感兴趣,而我在这里没有看到,因此我将发布这个示例,该示例与Rails UJS和Turbolinks配合使用效果很好。

首先,您设置控制器以返回HTML作为局部模板:

format.html { render partial: "new_expense" }

接下来,在 app/views/expenses/new_daily.js.erb 中编写一个 JavaScript AJAX 函数:
var i = parseInt($('#daily').attr('data-num')) + 1;

$.ajax({
  url: '/daily',
  type: 'GET',
  dataType: 'html',
  contentType: "application/html",
  success: function(response) { 

      $('#daily').replaceWith(response)

      $('#daily').attr('data-num', i);
  }
});

这将会获取你的Rails partial作为一个html片段,你可以用它来替换你渲染页面的那一部分。你可以使用jQuery来获取你的data-num属性值,进行一些数学计算,在视图中替换partial,然后再次设置属性值。
你可能会问,为什么要费这么大劲去获取Rails partial并在页面上替换它,而不是只获取数据属性,对其进行数学计算,然后设置它?答案是,这是在处理UJS渲染Rails partial时处理异步响应时真正必要的最佳方法,也许是唯一的方法。
如果您正在处理来自服务器的异步响应,例如在create.js.erb模板中,则您的变量(例如@daily)不会反映出请求完成后所做的工作(例如,在像Sidekiq这样的后台服务器上进行处理)。在这种情况下,您没有最新的操作响应变量可以传递到js.erb文件中的Rails partial中,但是您也不能将javascript data响应传递到partial中,如本问题所指出的那样。
据我所知,这种方法是在接收到异步响应后获取完全更新的partial的唯一方法(未显示)。这使您可以获得最新的partial,允许您将javascript嵌入其中,并且足够灵活,可以在几乎任何用例中工作。

-1

让我们确保我们互相理解。您的erb模板(new_daily.js.erb)将在服务器端进行处理,Ruby代码将被评估(在<% %>之内),替换后,生成的JavaScript将发送到浏览器。在客户端上,浏览器将评估此JavaScript代码并将变量i分配一个值。
那么,您想何时传递该变量,并传递给哪个部分?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接