4

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 e.g.:

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 e.g. 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

1
  • Are there going to be any other event types besides resource create/update/delete? If not, why standard flash messages don't fit? Commented Jul 30, 2011 at 22:08

4 Answers 4

6
+50

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
   });
});
Sign up to request clarification or add additional context in comments.

Comments

2

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.

Comments

0

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.

4 Comments

That seems like a viable alternative, however considerably more verbose. Could you give some thoughts as to why it would be preferable to my proposed solution? Thanks!
You have to judge based on your situation.. its not necessarily more preferable.... they're very similar actually.. The major difference is that mine uses hashtags and is completely client side. Independent of the backend you use. Yours is mainly controller dependant. I don't see much more beyond that though.. after that, its your call
Keep in mind, you don't need most of the broilerplate I put in there.. its just for completeness
Sure, just a couple of other points though are that it makes some assumptions about the existing hashtag, although they could be worked out by passing params rather than directly overwriting it. Additionally, it depends on a redirect, rather than a render and would require a bit of extra work to queue multiple events in one request/response cycle. All small problems that could be worked around though
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.