简体   繁体   中英

Rails - trigger javascript events from controllers

I'm thinking of implementing something like the following and would like to know a) if it's possibly a really bad idea for some reason I haven't thought of, and b) if not - is there an existing gem out there to do it.

Basically, I'd like to be able to queue javascript events from my rails controllers so that on next render all queued events would be triggered and removed from the queue. Sort of like the flash mechanism but for events instead. So eg:

in my controller:

def create
  if resource.create 
    add_event('resourceCreated', :id => resource.id)
  end
end

and in my application layout something like:

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

Any thoughts?

Edit: This would be useful eg when an item is created, the server may redirect to the edit form for said item, or may redirect to the index action for the relevant controller. These pages don't know that an item was just created. However perhaps I want to do something like close a dialog window if the item was created successfully but leave it open if it was not, or any number of other possible reasons I may need to know about it. Obviously not just relevant for creates, that's just the example I'm using to illustrate the problem

Edit: Bounty goes to whoever persuades me convincingly one way or the other that this is a good/bad idea or provides a better alternative

I see what you are trying to do, but you need to be careful about keeping things separate.

What I would do in this situation is create a hash and then #to_json it in your view. Let's say at the bottom of your action

controller

@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
   });
});

I would suggest doing this with Rails' flash message mechanism, which is already there for precisely the purpose of letting the user know about any server-side events that happened since the last request. Stick a hidden machine-parseable description chunk onto the end of each flash message, write a Ruby API that makes it easy to add such chunks, and then something in your view (or perhaps written in JS) to retrieve and deal with them as necessary.

As a bonus, you also get to tell the user directly about server-side events in the same motion, even if they don't have JS enabled or available in their browser.

Here's what you can do...

Send the user to a page, with a givven hashtag

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

which maps to:

/path/tosomething#initiate_awesome

In that page, once the document is loaded, put in na line to check the page hashtag, and execute a js evven depending on that hashtag. Example here shown for Jquery with Haml and using Jquery events:

%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');
      }
     });

With this setup, once the page loads, it'll trigger your js event and do what you want. aWesomeness acquired.

For bonus points, since this js code is in your template, you can render the event names in the js snippet from ruby by the controlleer, and have the event chain written out to js for further parsing.

Hi you can trigger js events from your controller in the following way.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM