Nesting widgets, pt. 1
Since we moved our twitter widget to a namespace let’s learn how nesting widgets works. The panel widget should host the form to hide implementation details to the outside.
Public nesting
What sounds like a statement of facts is a simple way to setup a widget tree. Public nesting usually happens in the controller’s has_widgets block.
Instead of adding the form to root, we add it to the panel widget (line 5).
The panel widget just got daddy! We can safely render the child inside the panel’s display view.
You can use #render_widget in widget views and in controller views. Check the API to learn more.
Now that we render the child in the widget, we should remove the rendering from the controller view. Otherwise, the form would be rendered twice, which is not what we want.
By moving the #render_widget call from the controller’s view into the panel’s view we remove responsibility from the controller – it shouldn’t care about the internals of the panel widget.
Private nesting
If the controller shouldn’t worry about the widget’s internals, why does it still have to setup a widget tree? That’s a legitimate complaint.
We can move the tree setup into the panel widget – that’s why widgets can have their own has_widgets blocks.
The has_widget block in widget classes is executed in instance context, so you may access self and instance variables. In controllers, you may use the controller instance. Check the API to learn more.
This almost looks identical to the controller – however, there is no knowledge about the widget’s internal setup in the controller anymore. All it knows is “There’s a twitter panel widget” – the rest is hidden in the widget itself.
The controller now has a despeckled has_widgets block, again.
Summary
A short process overview might help understanding what’s going on.
- The controller adds the panel to
root. - In its
index.html.hamlview, it renders the panel, only. - The panel internally has a child widget, the form.
- In the panel’s
display.hamlview the child gets rendered at the appropriate place using#render_widget. - The child widget renders the form in its own
#displaystate.
That’s nesting!
This is pretty cool. The form shows up in the panel. If only the list would update after we submit the form. Let’s explore how bubbling events can help here.

