Namespacing widgets
This guide is for you, Kevin!
We decided to extract the form behaviour from our twitter widget into a separate component. We will get two widgets then, one listing items while hosting the form, and the form itself.
It’s good choice to put these connected components into a namespace.
Generating namespaced widgets
Let the generator create a namespaced form widget.
rails g apotomo:widget Twitter::Form display -e haml
create app/widgets/twitter/form_widget.rb
Cool, the generator pushes the widget into a sub-directory. That’s cause we provided the namespaced widget name Twitter::Form.
Looking at the new widget class we figure it’s inside a module.
Namespacing?
So, namespacing is basically pushing widget classes into the namespace module and packing the assets into a subdirectory.
After moving the TwitterWidget to Twitter::PanelWidget manually things look like this:
| Original file | After namespacing |
| app/widgets/twitter_widget.rb | app/widgets/twitter/panel_widget.rb |
| app/widgets/twitter/display.html.haml | app/widgets/twitter/panel/display.html.haml |
| app/widgets/twitter/form.haml | app/widgets/twitter/form/display.html.haml |
| - | app/widgets/twitter/form_widget.rb |
Refactoring
We need to move some code portions from the original TwitterWidget to the new Twitter::FormWidget.
After a bit of refactoring, the form widget looks like this.
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 replace :state => :display 14 else 15 replace :view => :display 16 end 17 end 18 19end
That’s old code we already know, in a new shell. Three things changed here, so far.
- When rendering the
#displaystate we expect blank form, so we create a newTweetinstance (line 5). - The
#process_tweetmethod is called#submitnow (line 9). This way we can use the shorthand form ofresponds_to_event(line 2). - When processing the form submission we introduce a decider. If the input is valid invoke the
#displaystate and thus render a new, blank form (line 13). Otherwise, simply render thedisplayview and reuse our@tweetinstance variable with its error messages (line 15).
The form view changed a bit, too.
We simply wrap the form in a #widget_div so we can use #replace (line 1).
Another step for now is updating the panel display view – we don’t want to render the #form state anymore, since this is a discrete stand-alone widget now.
Using namespaced widgets
The widget tree in the DashboardController needs a bit of updating to show our namespaced widgets.
Here, we add two widgets to root. Notice how I refer to the namespaced class names by separating the module and class with a / as in twitter/panel.
The panel widget gets an explicit id :twitter (line 4). The second widget will be named :twitter_form explicitely (line 5).
Understanding the id naming is especially important when it comes to rendering.
That works, both widgets are rendered. However, the tweets list is not updated after a successful submission.
Well, of course it doesn’t update!? How would the panel know about updates from the separated form widget? We will use nesting and bubbling events in the next chapters to accomplish that! Yay!

