3 Reaction::Manual::Widgets - Creating and extending Reaction Widgets
5 =head1 WHAT IS A WIDGET
7 A widget represents the Perl code used by the layout. Which widget to use
8 can be set with the C<=widget> directive. For more on templates, look at
9 L<Reaction::Manual::Templates>.
11 The widget that is used defaults to a name built by the controller class
12 and the name of the action. E.g. the action C<MyApp::Controller::Foo-E<gt>bar>
13 would assume a widget named C<Foo::Bar> and look for it in the C<widget_search_path>
14 defined in the C<share/skin/$skin_name/skin.conf> or the C<share/skin/defaults.conf>.
16 =head1 A SIMPLE WIDGET
18 The simplest widget would be this:
20 package MyApp::Widget::Foo;
21 use Reaction::UI::WidgetClass;
23 use namespace::autoclean;
25 __PACKAGE__->meta->make_immutable;
29 The use of L<Reaction::UI::WidgetClass> will import L<strict>, L<warnings>, L<Moose> and
30 L<Reaction::Class>. It will also set L<Reaction::UI::Widget> as the base class of the
31 widget. If you want to extend an existing widget rather than create a new one, use
36 Layouts can use the C<=for layout $fragment> POD syntax to define fragments and use them
37 like usual L<Template> variables.
39 But sometimes it is desirable to have a fragment that invokes Perl code in the widget
40 to render certain outputs. For this, the widget has its own mechanisms to handle
43 =head2 Implementing a fragment
45 A layout fragment can access the widgets attributes and other fragments like normal
46 L<Template> variables. But if a widget implements a fragment, that implementation will
47 be used to provide the data and some additional control over the rendering of the layout.
49 This abstracts the data manipulation view logic from the layouting view logic.
51 A widget can implement a new fragment like this:
53 package MyApp::Widget::Foo;
54 use Reaction::UI::WidgetClass;
56 use namespace::autoclean;
58 implements fragment now {
59 arg timestamp => time();
62 __PACKAGE__->meta->make_immutable;
66 Now we can layout the provided data like this:
78 <p>Timestamp: [% timestamp %]</p>
82 The C<widget> fragment is the root fragment of every widget. The widget directive sets
83 the desired widget to C<Foo>. One of our C<widget_search_path>s should contain
84 C<MyApp::Widget>, so the widget class defined above can be found.
86 The C<widget> fragment defined here will render the C<now> fragment implemented by the
87 widget and layed out by the layout template. Assuming the current timestamp is
88 C<1234567890>, the rendered output will look like this:
92 <p>Timestamp: 1234567890</p>
94 Let us take a closer look at the fragment implementation in the widget:
96 implements fragment now {
97 arg timestamp => time();
100 This syntax might look a bit unusual, but it's not a source filter. The declarative style
101 is provided by L<Devel::Declare>. This implements a fragment named C<now> in the current
102 widget. The body uses the C<arg> keyword to provide a new argument C<timestamp> to the
103 template with the value of the current return value of C<time()>.
105 =head1 Extending a fragment
107 Sometimes you don't want to redefine how a fragment is implemented, but merely extend on
108 the current definition. An example would be adding the total number of entries in a
109 collection below the listing of the entries.
111 Fortunately, L<Reaction> is based on L<Moose> and trying to stay as flexible as possible.
112 In this case, Reaction allows us to use Moose method modifiers with fragments:
114 package MyApp::Widget::Bar;
115 use Reaction::UI::WidgetClass;
117 use namespace::autoclean;
119 extends 'MyApp::Widget::Foo';
121 around fragment now {
123 arg timestamp => sprintf '"%s"', $_{timestamp};
126 __PACKAGE__->meta->make_immutable;
130 The C<call_next> keyword will call the next implementation in the inheritance tree, just
131 like it would call the next fragment when used in the layout template.
133 The global hash C<%_> is used to provide the fragment arguments to the code block
134 implementing it. For example, the viewport would be available in C<$_{viewport}>.
136 Besides C<around>, you can also use C<before> and C<after>.
138 =head1 Iterating over a fragment
140 Many fragments are intended to be iterated over a collection of items. An example
141 implementation of this is listed below:
143 package MyApp::Widget::Baz
144 use Reaction::UI::WidgetClass;
148 use namespace::autoclean;
150 my @Fields = qw( year month day hour minute second );
152 implements fragment now {
153 arg dt_obj => DateTime->now;
154 render datetime_field => over [@Fields];
157 implements fragment datetime_field {
158 arg field_name => $_;
159 arg field_value => $_{dt_obj}->$_();
162 __PACKAGE__->meta->make_immutable;
166 Which could have a layout template like this:
182 =for layout datetime_field
184 <li>[% field_name | ucfirst %]: [% field_value %]</li>
188 The C<widget> fragment defined in the layout template will render the C<now> fragment
189 implemented in the widget class. It is setting the C<dt_obj> argument to a L<DateTime>
190 object representing the current date and time. Then it will C<render> the fragment
191 C<datetime_field> once for every item in the C<@Fields> array.
193 The global topic variable C<$_> will be set to each corresponding value in the arguments
194 to C<over>. The C<datetime_field> fragment will then for each field name set C<field_name>
195 to the aforementioned value, and store the result of the method of that name on the C<dt_obj>
196 in the C<field_value> argument.
198 The layout simply formats and puts the components in place.
200 =head1 WIDGETS PROVIDED BY REACTION
204 =item L<Reaction::UI::Widget::SiteLayout>
206 The common wrapper around the fully rendered site.
208 =item L<Reaction::UI::Widget::ListView>
210 Extends L<Reaction::UI::Widget::Grid> to provide actions and paging.
212 =item L<Reaction::UI::Widget::Object>
214 Rendering of a single object by a collection of viewports.
216 =item L<Reaction::UI::Widget::Container>
218 A base class that automatically provides callbacks to render attributes containing
219 viewports on the current viewport.
221 =item L<Reaction::UI::Widget::Collection>
223 Renders a collection of member viewports in the current viewport.
225 =item L<Reaction::UI::Widget::Grid>
227 A subclass of L<Reaction::UI::Widget::Collection> providing header and footer
228 as well as member actions. The C<default> skin contains layout sets to output
229 this widget as a HTML table.
231 =item L<Reaction::UI::Widget::Image>
233 An image with optional width and height properties.
235 =item L<Reaction::UI::Widget::Field>
237 Base widget for fields. Contains a list of subclasses.
239 =item L<Reaction::UI::Widget::Action>
241 A widget representing a mutation of an object.
243 =item L<Reaction::UI::Widget::Action::Link>
245 Object mutation widget rendering a hyperlink.
247 =item L<Reaction::UI::Widget::Data>
249 Renders the data stored in the viewport's C<args> attribute.
251 =item L<Reaction::UI::Widget::Value>
253 Will take the C<value_string> or C<value> viewport method return value and provide it as
254 argument C<value> to the C<widget> fragment. It also contains a list of subclasses.
256 =item L<Reaction::UI::Widget::URI>
258 A hyperlink reference via an URI stored in the viewport.
266 =item * L<Reaction::UI::WidgetClass>
268 =item * L<Reaction::UI::Widget>
270 =item * L<Reaction::Manual::Templates>
276 See L<Reaction::Class> for authors.
280 See L<Reaction::Class> for the license.