Passing Messages with Events

In this Chapter events, trigger, messages
Github code message-passing
Versions 1.1
Next chapter

In this guide we’re gonna explore an interesting feature related with events, which is called message passing.

The example in this guide may look weird, and it actually is – let’s use it for discussion and learning a couple of things about Apotomo.

Events can transport payload

In the last chapter the :newTweet event urged our panel widget to redraw the entire tweets list. As it consumes a lot of time to reload the tweets from the database instead we could also just redraw the new tweet.

How would the panel know which tweet is the one just created? The form widget could propagate that using the event.

app/widgets/twitter/form_widget.rb
 1class Twitter::FormWidget < Apotomo::Widget
 2  responds_to_event :submit
 3  
 4  def display
 5    @tweet = Tweet.new
 6    render
 7  end
 8
 9  def submit(evt)
10    @tweet = Tweet.new
11    
12    if @tweet.update_attributes(evt[:tweet])
13      trigger :newTweet, :tweet => @tweet
14      replace :state => :display
15    else
16      replace :view => :display
17    end
18  end
19
20end

We simply append the new tweet to the triggered event (line 13). States triggered by this event can now access this payload data – cool!

The event object speaks!

Let’s see how we can query the event object for the new tweet.

app/widgets/twitter/panel_widget.rb
 1class Twitter::PanelWidget < Apotomo::Widget
 2  responds_to_event :newTweet, :with => :redraw_list
 3  
 4  has_widgets do
 5    self << widget("twitter/form", :tweet_form)
 6  end
 7  
 8  
 9  def display
10    @tweets = Tweet.find(:all)
11    render
12  end
13  
14  def list(tweets)
15    render :locals => {:tweets => tweets}
16  end
17  
18  def redraw_list(evt)
19    text = evt[:tweet].text
20    
21    render :text => "$(\"##{widget_id} ul\").append(\"<li>#{text}</li>\");"
22  end
23  
24end

I tweaked the #redraw_list method. What re-rendered the display state now sends back one new <li>...</li> item, only (line 18-22).

By using evt[:tweet] I can access the tweet model sitting piggy-back on the event triggered in the form (line 19).

Sending back plain JavaScript

Note how I don’t use #replace anymore but send back hand-made JavaScript (line 21).

The content sent to the browser roughly looks like this.

$("#twitter ul").append("<li>boardumb</li>");

This simply appends the new tweet to the list. Nothing more.

Discussion

The alert reader with the desire for strong encapsulation will notice a small interface violation here: The panel widget knows about the HTML format of a list item. This should be handled by the list state, or by a separate tweet widget.

We’re gonna cover that in the next chapter.


blog comments powered by Disqus