Rails - 从控制器触发JavaScript事件

4
我想实现以下类似的功能,并希望知道a)是否可能因为我没有考虑到的某些原因而是一个非常糟糕的想法,以及b)如果不是-是否存在现有的gem来完成它。
基本上,我想能够从我的rails控制器中排队javascript事件,以便在下次渲染时触发并从队列中删除所有排队的事件。有点像闪存机制,但用于事件。例如:
在我的控制器中:
def create
  if resource.create 
    add_event('resourceCreated', :id => resource.id)
  end
end

在我的应用程序布局中,类似以下内容:

%javascript
  - @events.each do |e|
    $(document).trigger(#{e.event_name}, #{e.event_data})

有什么想法吗?
编辑:例如,当创建一个项目时,服务器可能会重定向到所述项目的编辑表单,也可能会重定向到相关控制器的索引动作。这些页面不知道刚刚创建了一个项目。然而,也许我想做一些事情,比如如果项目创建成功就关闭对话框窗口,但如果未成功则保持打开状态,或者其他任何可能需要知道它的原因。显然不仅适用于创建,这只是我用来说明问题的例子。
编辑:奖金将授予那些能够有说服力地向我证明这是一个好/坏想法或提供更好替代方案的人。

除了资源的创建/更新/删除之外,还会有其他类型的事件吗?如果没有,为什么标准的闪存消息不适用? - RocketR
4个回答

5

我知道你想做什么,但你需要小心保持事物的分离。

在这种情况下,我会创建一个哈希表,然后在视图中将其 #to_json。假设在你的操作底部:

控制器

@events = [
   { :type => "item_created", :message => "Woohoo! Item was created"}
]

index.html.erb

<div>Your usual stuff goes here</div>
<script type="text/javascript" charset="utf-8">
  var events = <%= raw @events.to_json %> // You must make sure it's properly sanitised
</script>

jQuery

$.ready(function() { 
   events.each(function () {
      // ... Do what you need to with this
   });
});

2
我建议使用Rails的闪存消息机制来完成这个任务,该机制旨在让用户了解自上次请求以来发生的任何服务器端事件。在每个闪存消息的末尾添加一个隐藏的机器可解析的描述块,编写一个Ruby API使添加此类块变得容易,然后在您的视图中(或者可能是使用JS编写的)检索并处理它们。
作为奖励,即使用户没有启用或在其浏览器中不可用JS,您也可以直接告知用户有关服务器端事件的信息。

0

你可以通过以下方式从控制器触发js事件。

def create
  if resource.create 
    add_event('resourceCreated', :id => resource.id)
  end
    render :update do |page|
      page << "dismiss()"
    end
end

0

你可以做以下事情...

将用户发送到一个带有给定哈希标签的页面

= link_to "Get aWesome!", awesomem_page_path + '#initiate_awesome' 

对应到:

/path/tosomething#initiate_awesome

在该页面中,一旦文档加载完成,插入一行代码以检查页面的哈希标签,并根据该哈希标签执行JS事件。以下是使用Haml和Jquery事件的示例:
%h1  aWesomeness is about to happen...

- content_for :jquery do
  :javascript
    $(document).ready(function(){
      if (document.location.hash === "#initiate_awesome"){
        $('#amazing_div').trigger('awesome_event');
      } else {
            $('#not_so_cool_div').trigger('ultimate_letdown');
      }
     });

通过这个设置,一旦页面加载,它将触发您的js事件并执行您想要的操作。已获得卓越性。

对于额外的加分项,由于此js代码位于您的模板中,您可以通过控制器从ruby渲染js片段中的事件名称,并将事件链写入js以进行进一步解析。


这似乎是一个可行的替代方案,但更为冗长。您能否说一些原因,解释为什么这比我提出的解决方案更好呢?谢谢! - jcoffey
你必须根据自己的情况来判断,这并不一定更可取......实际上它们非常相似。主要区别在于我的使用了标签,完全在客户端进行,独立于你使用的后端。而你的则主要依赖于控制器。除此之外,我没有看到更多的区别......在那之后,就由你决定了。 - noli
记住,你不需要我放在那里的大部分样板代码..它只是为了完整性。 - noli
当然,还有一些其他的要点需要注意,它对现有的标签做了一些假设,虽然可以通过传递参数而不是直接覆盖来解决。此外,它依赖于重定向而不是渲染,并且需要额外的工作才能在一个请求/响应周期中排队多个事件。这些都是可以解决的小问题。 - jcoffey

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