1 #============================================================= -*-perl-*-
3 # Template::Manual::Views
6 # Andy Wardley <abw@wardley.org>
9 # Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
11 # This module is free software; you can redistribute it and/or
12 # modify it under the same terms as Perl itself.
14 #========================================================================
18 Template::Manual::Views - Template Toolkit views (experimental)
22 A view is effectively a collection of templates and/or variable
23 definitions which can be passed around as a self-contained unit. This
24 then represents a particular interface or presentation style for other
25 objects or items of data.
27 You can use views to implement custom "skins" for an application or
28 content set. You can use them to help simplify the presentation of
29 common objects or data types. You can even use then to automate the
30 presentation of complex data structures such as that generated in an
31 C<XML::DOM> tree or similar. You let an iterator do the walking, and the
32 view does the talking (or in this case, the presenting). Voila - you
33 have view independant, structure shy traversal using templates.
35 In general, views can be used in a number of different ways to achieve
36 several different things. They elegantly solve some problems which
37 were otherwise difficult or complicated, and make easy some things
38 that were previously hard.
40 At the moment, they're still very experimental. The directive syntax
41 and underlying API are likely to change quite considerably over the
42 next version or two. Please be very wary about building your
43 multi-million dollar e-commerce solutions based around this feature.
45 =head1 Views as Template Collectors/Providers
47 The C<VIEW> directive starts a view definition and includes a name by
48 which the view can be referenced. The view definition continues up to
49 the matching C<END> directive.
55 The first role of a view is to act as a collector and provider of templates.
56 The C<include()> method can be called on a view to effectively do the same
57 thing as the C<INCLUDE> directive. The template name is passed as the first
58 argument, followed by any local variable definitions for the template.
60 [% myview.include('header', title='The Title') %]
63 [% INCLUDE header title='The Title' %]
65 Views accept a number of configuration options which can be used to control
66 different aspects of their behaviour. The 'C<prefix>' and 'C<suffix>' options
67 can be specified to add a fixed prefix and/or suffix to the name of each template.
77 [% myview.include('header', title='The Title') %]
81 [% INCLUDE my/header.tt2 title='The Title' %]
83 Views provide an C<AUTOLOAD> method which maps method names to the
84 C<include()> method. Thus, the following are all equivalent:
86 [% myview.include('header', title='Hello World') %]
87 [% myview.include_header(title='Hello World') %]
88 [% myview.header(title='Hello World') %]
90 =head1 Local BLOCK Definitions
92 A C<VIEW> definition can include C<BLOCK> definitions which remain local to
93 the view. A request for a particular template will return a C<BLOCK>,
94 if defined, in preference to any other template of the same name.
112 [% INCLUDE foo %] # public foo block
113 [% plain.foo %] # plain foo block
114 [% fancy.foo %] # fancy foo block
116 In addition to C<BLOCK> definitions, a C<VIEW> can contain any other
117 template directives. The entire C<VIEW> definition block is processed to
118 initialise the view but no output is generated (this may change RSN -
119 and get stored as 'C<output>' item, subsequently accessible as C<[%
120 view.output %]>). However, directives that have side-effects, such as
121 those that update a variable, will have noticable consequences.
123 =head1 Preserving Variable State within Views
125 Views can also be used to save the values of any existing variables,
126 or to create new ones at the point at which the view is defined.
127 Unlike simple template metadata (C<META>) which can only contain static
128 string values, the view initialisation block can contain any template
129 directives and generate any kind of dynamic output and/or data items.
131 [% VIEW my_web_site %]
132 [% view.title = title or 'My Cool Web Site' %]
133 [% view.author = "$abw.name, $abw.email" %]
134 [% view.sidebar = INCLUDE my/sidebar.tt2 %]
137 Note that additional data items can be specified as arguments to the C<VIEW>
138 directive. Anything that doesn't look like a configuration parameter is
139 assumed to be a data item. This can be a little hazardous, of course, because
140 you never know when a new configuration item might get added which interferes
147 title = title or 'My Cool Web Site'
148 author = "$abw.name, $abw.email"
149 sidebar = INCLUDE my/sidebar.tt2
154 Outside of the view definition you can access the view variables as, for
157 [% my_web_site.title %]
159 One important feature is the equivalence of simple variables and templates.
160 You can implement the view item 'C<title>' as a simple variable, a template
161 defined in an external file, possibly with a prefix/suffix automatically
162 appended, or as a local C<BLOCK> definition within the C<[% VIEW %] ... [% END %]>
163 definition. If you use the syntax above then the view will Do The Right
164 Thing to return the appropriate output.
166 At the C<END> of the C<VIEW> definition the view is "sealed" to prevent you
167 from accidentally updating any variable values. If you attempt to change
168 the value of a variable after the C<END> of the C<VIEW> definition block then
169 a C<view> error will be thrown.
172 my_web_site.title = 'New Title';
178 The error above will be reported as:
180 view error - cannot update item in sealed view: title
182 The same is true if you pass a parameter to a view variable. This is
183 interpreted as an attempt to update the variable and will raise the same
186 [% my_web_site.title('New Title') %] # view error!
188 You can set the C<silent> parameter to have the view ignore these
189 parameters and simply return the variable value.
193 title = title or 'My Cool Web Site'
198 [% my_web_site.title('Blah Blah') %] # My Cool Web Site
200 Alternately, you can specify that a view is unsealed allowing existing
201 variables to be updated and new variables defined.
205 title = title or 'My Cool Web Site'
210 [% my_web_site.title('Blah Blah') %] # Blah Blah
211 [% my_web_site.title %] # Blah Blah
213 =head2 Inheritance, Delegation and Reuse
215 Views can be inherited from previously defined views by use of the C<base>
216 parameter. This example shows how a base class view is defined which
217 applies a C<view/default/> prefix to all template names.
219 [% VIEW my.view.default
220 prefix = 'view/default/';
226 [% my.view.default.header(title='Hello World') %]
228 is now equivalent to:
230 [% INCLUDE view/default/header title='Hello World' %]
232 A second view can be defined which specifies the default view as a
235 [% VIEW my.view.fancy
236 base = my.view.default
237 prefix = 'view/fancy/';
243 [% my.view.fancy.header(title='Hello World') %]
247 [% INCLUDE view/fancy/header title='Hello World' %]
249 or if that doesn't exist, it will be handled by the base view as:
251 [% INCLUDE view/default/header title='Hello World' %]
253 When a parent view is specified via the C<base> parameter, the
254 delegation of a view to its parent for fetching templates and accessing
255 user defined variables is automatic. You can also implement your own
256 inheritance, delegation or other reuse patterns by explicitly
257 delegating to other views.
265 <plain>[% PROCESS foo %]</plain>
271 [% plain.foo | replace('plain', 'fancy') %]
275 [% plain.foo %] # <plain>public foo block</plain>
276 [% fancy.foo %] # <fancy>public foo block</fancy>
278 Note that the regular C<INCLUDE/PROCESS/WRAPPER> directives work entirely
279 independantly of views and will always get the original, unaltered
280 template name rather than any local per-view definition.
282 =head2 Self-Reference
284 A reference to the view object under definition is available with the
285 C<VIEW ... END> block by its specified name and also by the special name
286 'C<view>' (similar to the C<my $self = shift;> in a Perl method or the
287 'C<this>' pointer in C++, etc). The view is initially unsealed allowing
288 any data items to be defined and updated within the C<VIEW ... END>
289 block. The view is automatically sealed at the end of the definition
290 block, preventing any view data from being subsequently changed.
292 (NOTE: sealing should be optional. As well as sealing a view to prevent
293 updates (C<SEALED>), it should be possible to set an option in the view to
294 allow external contexts to update existing variables (C<UPDATE>) or even
295 create totally new view variables (C<CREATE>)).
298 [% fancy.title = 'My Fancy Title' %]
299 [% fancy.author = 'Frank Open' %]
300 [% fancy.col = { bg => '#ffffff', bar => '#a0a0ff' } %]
306 [% view.title = 'My Fancy Title' %]
307 [% view.author = 'Frank Open' %]
308 [% view.col = { bg => '#ffffff', bar => '#a0a0ff' } %]
311 It makes no real difference in this case if you refer to the view by
312 its name, 'C<fancy>', or by the general name, 'C<view>'. Outside of the
313 view block, however, you should always use the given name, 'C<fancy>':
319 The choice of given name or 'C<view>' is much more important when it
320 comes to C<BLOCK> definitions within a C<VIEW>. It is generally recommended
321 that you use 'C<view>' inside a C<VIEW> definition because this is guaranteed
322 to be correctly defined at any point in the future when the block gets
323 called. The original name of the view might have long since been changed
324 or reused but the self-reference via 'C<view>' should always be intact and
327 Take the following VIEW as an example:
330 [% view.title = 'Hello World' %]
332 Title: [% view.title %]
336 Even if we rename the view, or create a new C<foo> variable, the header
337 block still correctly accesses the C<title> attribute of the view to
338 which it belongs. Whenever a view C<BLOCK> is processed, the C<view>
339 variable is always updated to contain the correct reference to the
340 view object to which it belongs.
343 [% foo = { title => "New Foo" } %] # no problem
344 [% bar.header %] # => Title: Hello World
346 =head2 Saving References to External Views
348 When it comes to view inheritance, it's always a good idea to take a
349 local copy of a parent or delegate view and store it as an attribute
350 within the view for later use. This ensures that the correct view
351 reference is always available, even if the external name of a view
359 [% view.plain = plain %]
361 [% view.plain.foo | replace('plain', 'fancy') %]
365 [% plain.foo %] # => <plain>public foo block</plain>
366 [% plain = 'blah' %] # no problem
367 [% fancy.foo %] # => <fancy>public foo block</fancy>
369 =head2 Views as Data Presenters
371 Another key role of a view is to act as a dispatcher to automatically
372 apply the correct template to present a particular object or data
373 item. This is handled via the C<print()> method.
380 Some text: [% item %]
385 [% FOREACH key = item.keys.sort -%]
386 [% key %] => [% item.$key %]
391 a list: [% item.sort.join(', ') %]
396 We can now use the view to print text, hashes or lists. The C<print()>
397 method includes the right template depending on the typing of the
398 argument (or arguments) passed.
400 [% some_text = 'I read the news today, oh boy.' %]
401 [% a_hash = { house => 'Lords', hall => 'Albert' } %]
402 [% a_list = [ 'sure', 'Nobody', 'really' ] %]
404 [% view.print(some_text) %]
405 # Some text: I read the news today, oh boy.
407 [% view.print(a_hash) %]
411 [% view.print(a_list) %]
412 # a list: Nobody, really, sure
414 You can also provide templates to print objects of any other class.
415 The class name is mapped to a template name with all non-word
416 character sequences such as 'C<::>' converted to a single 'C<_>'.
421 thingies: [% view.print(item.thingies) %]
422 doodahs: [% view.print(item.doodahs) %]
426 [% USE fubar = Foo::Bar(...) %]
428 [% foo.print(fubar) %]
430 Note how we use the view object to display various items within the
431 objects ('C<thingies>' and 'C<doodahs>'). We don't need to worry what
432 kind of data these represent (text, list, hash, etc) because we can
433 let the view worry about it, automatically mapping the data type to
434 the correct template.
436 Views may define their own type =E<gt> template map.
439 map = { TEXT => 'plain_text',
440 ARRAY => 'show_list',
442 My::Module => 'template_name'
443 default => 'any_old_data'
446 [% BLOCK plain_text %]
453 They can also provide a C<default> map entry, specified as part of the C<map>
454 hash or as a parameter by itself.
466 [% view.map = { ... }
467 view.default = 'whatever'
472 The C<print()> method provides one more piece of magic. If you pass it a
473 reference to an object which provides a C<present()> method, then the method
474 will be called passing the view as an argument. This then gives any object a
475 chance to determine how it should be presented via the view.
480 my ($self, $view) = @_;
481 return "a Foo::Bar object:\n"
482 . "thingies: " . $view->print($self->{ _THINGIES }) . "\n"
483 . "doodahs: " . $view->print($self->{ _DOODAHS }) . "\n";
486 The object is free to delve deeply into its innards and mess around with
487 its own private data, before presenting the relevant data via the view.
488 In a more complex example, a C<present()> method might walk part of a tree
489 making calls back against the view to present different nodes within the
490 tree. We may not want to expose the internal structure of the tree
491 (because that would break encapsulation and make our presentation code
492 dependant on it) but we want to have some way of walking the tree and
493 presenting items found in a particular manner.
495 This is known as I<Structure Shy Traversal>. Our view object doesn't require
496 prior knowledge about the internal structure of any data set to be able
497 to traverse it and present the data contained therein. The data items
498 themselves, via the C<present()> method, can implement the internal iterators
499 to guide the view along the right path to presentation happiness.
501 The upshot is that you can use views to greatly simplify the display
502 of data structures like C<XML::DOM> trees. The documentation for the
503 C<Template::Plugin::XML::DOM> module contains an example of this. In
504 essence, it looks something like this:
508 <user name="Andy Wardley">
509 <project id="iCan" title="iCan, but theyCan't"/>
510 <project id="p45" title="iDid, but theyDidn't"/>
517 User: [% item.name %]
518 [% item.content(myview) %]
522 Project: [% project.id %] - [% project.name %]
528 [% USE dom = XML.DOM %]
529 [% fancy.print(dom.parse(xml_source)) %]
534 Project: iCan - iCan, but theyCan't
535 Project: p45 - iDid, but theyDidn't
537 The same approach can be applied to many other areas. Here's an example from
538 the C<File>/C<Directory> plugins.
545 [% BLOCK directory %]
547 [% item.content(myview) FILTER indent %]
551 [% USE dir = Directory(dirpath) %]
552 [% myview.print(dir) %]
554 And here's the same approach use to convert POD documentation to any
555 other format via template.
557 [% # load Pod plugin and parse source file into Pod Object Model
559 pom = Pod.parse_file(my_pod_file);
561 # define view to map all Pod elements to "pod/html/xxx" templates
566 # now print document via view (i.e. as HTML)
570 Here we simply define a template prefix for the view which causes the
571 view to look for C<pod/html/head1>, C<pod/html/head2>, C<pod/html/over>
572 as templates to present the different sections of the parsed Pod document.
574 There are some examples in the Template Toolkit test suite: F<t/pod.t> and
575 F<t/view.t> which may shed some more light on this. See the distribution
576 sub-directory F<examples/pod/html> for examples of Pod -E<gt> HTML templates.
582 # perl-indent-level: 4
583 # indent-tabs-mode: nil
586 # vim: expandtab shiftwidth=4: