1Template::Manual::ViewsU(s3e)r Contributed Perl DocumentaTteimopnlate::Manual::Views(3)
2
3
4

NAME

6       Template::Manual::Views - Template Toolkit views (experimental)
7

DESCRIPTION

9       A view is effectively a collection of templates and/or variable defini‐
10       tions which can be passed around as a self-contained unit.  This then
11       represents a particular interface or presentation style for other
12       objects or items of data.
13
14       You can use views to implement custom "skins" for an application or
15       content set.  You can use them to help simplify the presentation of
16       common objects or data types.  You can even use then to automate the
17       presentation of complex data structures such as that generated in an
18       XML::DOM tree or similar.  You let an iterator do the walking, and the
19       view does the talking (or in this case, the presenting).  Voila - you
20       have view independant, structure shy traversal using templates.
21
22       In general, views can be used in a number of different ways to achieve
23       several different things.  They elegantly solve some problems which
24       were otherwise difficult or complicated, and make easy some things that
25       were previously hard.
26
27       At the moment, they're still very experimental.  The directive syntax
28       and underlying API are likely to change quite considerably over the
29       next version or two.  Please be very wary about building your multi-
30       million dollar e-commerce solutions based around this feature.
31
32       Views as Template Collectors/Providers
33
34       The VIEW directive starts a view definition and includes a name by
35       which the view can be referenced.  The view definition continues up to
36       the matching END directive.
37
38           [% VIEW myview %]
39              ...
40           [% END %]
41
42       The first role of a view is to act as a collector and provider of tem‐
43       plates.  The include() method can be called on a view to effectively do
44       the same thing as the INCLUDE directive.  The template name is passed
45       as the first argument, followed by any local variable definitions for
46       the template.
47
48           [% myview.include('header', title='The Title') %]
49
50           # equivalent to
51           [% INCLUDE header  title='The Title' %]
52
53       Views accept a number of configuration options which can be used to
54       control different aspects of their behaviour.  The 'prefix' and 'suf‐
55       fix' options can be specified to add a fixed prefix and/or suffix to
56       the name of each template.
57
58           [% VIEW myview
59                prefix = 'my/'
60                suffix = '.tt2' ;
61              END
62           %]
63
64       Now the call
65
66           [% myview.include('header', title='The Title') %]
67
68       is equivalent to
69
70           [% INCLUDE my/header.tt2  title='The Title' %]
71
72       Views provide an AUTOLOAD method which maps method names to the
73       include() method.  Thus, the following are all equivalent:
74
75           [% myview.include('header', title='Hello World') %]
76           [% myview.include_header(title='Hello World') %]
77           [% myview.header(title='Hello World') %]
78
79       Local BLOCK Definitions
80
81       A VIEW definition can include BLOCK definitions which remain local to
82       the view.   A request for a particular template will return a BLOCK, if
83       defined, in preference to any other template of the same name.
84
85           [% BLOCK foo %]
86              public foo block
87           [% END %]
88
89           [% VIEW plain %]
90              [% BLOCK foo %]
91              plain foo block
92              [% END %]
93           [% END %]
94
95           [% VIEW fancy %]
96              [% BLOCK foo %]
97              fancy foo block
98              [% END %]
99           [% END %]
100
101           [% INCLUDE foo %]       # public foo block
102           [% plain.foo %]         # plain foo block
103           [% fancy.foo %]         # fancy foo block
104
105       In addition to BLOCK definitions, a VIEW can contain any other template
106       directives.  The entire VIEW definition block is processed to ini‐
107       tialise the view but no output is generated (this may change RSN - and
108       get stored as 'output' item, subsequently accessible as [% view.output
109       %]).  However, directives that have side-effects, such as those that
110       update a variable, will have noticable consequences.
111
112       Preserving Variable State within Views
113
114       Views can also be used to save the values of any existing variables, or
115       to create new ones at the point at which the view is defined.  Unlike
116       simple template metadata (META) which can only contain static string
117       values, the view initialisation block can contain any template direc‐
118       tives and generate any kind of dynamic output and/or data items.
119
120           [% VIEW my_web_site %]
121              [% view.title   = title or 'My Cool Web Site' %]
122              [% view.author  = "$abw.name, $abw.email" %]
123              [% view.sidebar = INCLUDE my/sidebar.tt2 %]
124           [% END %]
125
126       Note that additional data items can be specified as arguments to the
127       VIEW directive.  Anything that doesn't look like a configuration param‐
128       eter is assumed to be a data item.  This can be a little hazardous, of
129       course, because you never know when a new configuration item might get
130       added which interferes with your data.
131
132           [% VIEW my_web_site
133                   # config options
134                   prefix = 'my/'
135                   # misc data
136                   title   = title or 'My Cool Web Site'
137                   author  = "$abw.name, $abw.email"
138                   sidebar = INCLUDE my/sidebar.tt2
139           %]
140              ...
141           [% END %]
142
143       Outside of the view definition you can access the view variables as,
144       for example:
145
146           [% my_web_site.title %]
147
148       One important feature is the equivalence of simple variables and tem‐
149       plates.  You can implement the view item 'title' as a simple variable,
150       a template defined in an external file, possibly with a prefix/suffix
151       automatically appended, or as a local BLOCK definition within the [%
152       VIEW %] ... [% END %] definition.  If you use the syntax above then the
153       view will Do The Right Thing to return the appropriate output.
154
155       At the END of the VIEW definition the view is "sealed" to prevent you
156       from accidentally updating any variable values.  If you attempt to
157       change the value of a variable after the END of the VIEW definition
158       block then an 'view' error will be thrown.
159
160           [% TRY;
161                my_web_site.title = 'New Title';
162              CATCH;
163                error;
164              END
165           %]
166
167       The error above will be reported as:
168
169           view error - cannot update item in sealed view: title
170
171       The same is true if you pass a parameter to a view variable.  This is
172       interpreted as an attempt to update the variable and will raise the
173       same warning.
174
175           [% my_web_site.title('New Title') %]    # view error!
176
177       You can set the 'silent' parameter to have the view ignore these param‐
178       eters and simply return the variable value.
179
180           [% VIEW my_web_site
181                   silent = 1
182                   title  = title or 'My Cool Web Site'
183                   # ... ;
184              END
185           %]
186
187           [% my_web_site.title('Blah Blah') %]   # My Cool Web Site
188
189       Alternately, you can specify that a view is unsealed allowing existing
190       variables to be updated and new variables defined.
191
192           [% VIEW my_web_site
193                   sealed = 0
194                   title  = title or 'My Cool Web Site'
195                   # ... ;
196              END
197           %]
198
199           [% my_web_site.title('Blah Blah') %]   # Blah Blah
200           [% my_web_site.title %]                # Blah Blah
201
202       Inheritance, Delegation and Reuse
203
204       Views can be inherited from previously defined views by use of the
205       'base' parameter.  This example shows how a base class view is defined
206       which applies a 'view/default/' prefix to all template names.
207
208           [% VIEW my.view.default
209                   prefix = 'view/default/';
210              END
211           %]
212
213       Thus the directive:
214
215           [% my.view.default.header(title='Hello World') %]
216
217       is now equivalent to:
218
219           [% INCLUDE view/default/header title='Hello World' %]
220
221       A second view can be defined which specifies the default view as a
222       base.
223
224           [% VIEW my.view.fancy
225                   base   = my.view.default
226                   prefix = 'view/fancy/';
227              END
228           %]
229
230       Now the directive:
231
232           [% my.view.fancy.header(title='Hello World') %]
233
234       will resolve to:
235
236           [% INCLUDE view/fancy/header title='Hello World' %]
237
238       or if that doesn't exist, it will be handled by the base view as:
239
240           [% INCLUDE view/default/header title='Hello World' %]
241
242       When a parent view is specified via the 'base' parameter, the delega‐
243       tion of a view to its parent for fetching templates and accessing user
244       defined variables is automatic.  You can also implement your own inher‐
245       itance, delegation or other reuse patterns by explicitly delegating to
246       other views.
247
248           [% BLOCK foo %]
249              public foo block
250           [% END %]
251
252           [% VIEW plain %]
253              [% BLOCK foo %]
254              <plain>[% PROCESS foo %]</plain>
255              [% END %]
256           [% END %]
257
258           [% VIEW fancy %]
259              [% BLOCK foo %]
260              [% plain.foo ⎪ replace('plain', 'fancy') %]
261              [% END %]
262           [% END %]
263
264           [% plain.foo %]     # <plain>public foo block</plain>
265           [% fancy.foo %]     # <fancy>public foo block</fancy>
266
267       Note that the regular INCLUDE/PROCESS/WRAPPER directives work entirely
268       independantly of views and will always get the original, unaltered tem‐
269       plate name rather than any local per-view definition.
270
271       Self-Reference
272
273       A reference to the view object under definition is available with the
274       VIEW ... END block by its specified name and also by the special name
275       'view' (similar to the "my $self = shift;" in a Perl method or the
276       'this' pointer in C++, etc).  The view is initially unsealed allowing
277       any data items to be defined and updated within the VIEW ... END block.
278       The view is automatically sealed at the end of the definition block,
279       preventing any view data from being subsequently changed.
280
281       (NOTE: sealing should be optional.  As well as sealing a view to pre‐
282       vent updates (SEALED), it should be possible to set an option in the
283       view to allow external contexts to update existing variables (UPDATE)
284       or even create totally new view variables (CREATE)).
285
286           [% VIEW fancy %]
287              [% fancy.title  = 'My Fancy Title' %]
288              [% fancy.author = 'Frank Open' %]
289              [% fancy.col    = { bg => '#ffffff', bar => '#a0a0ff' } %]
290           [% END %]
291
292       or
293
294           [% VIEW fancy %]
295              [% view.title  = 'My Fancy Title' %]
296              [% view.author = 'Frank Open' %]
297              [% view.col    = { bg => '#ffffff', bar => '#a0a0ff' } %]
298           [% END %]
299
300       It makes no real difference in this case if you refer to the view by
301       its name, 'fancy', or by the general name, 'view'.  Outside of the view
302       block, however, you should always use the given name, 'fancy':
303
304           [% fancy.title  %]
305           [% fancy.author %]
306           [% fancy.col.bg %]
307
308       The choice of given name or 'view' is much more important when it comes
309       to BLOCK definitions within a VIEW.  It is generally recommended that
310       you use 'view' inside a VIEW definition because this is guaranteed to
311       be correctly defined at any point in the future when the block gets
312       called.  The original name of the view might have long since been
313       changed or reused but the self-reference via 'view' should always be
314       intact and valid.
315
316       Take the following VIEW as an example:
317
318           [% VIEW foo %]
319              [% view.title = 'Hello World' %]
320              [% BLOCK header %]
321              Title: [% view.title %]
322              [% END %]
323           [% END %]
324
325       Even if we rename the view, or create a new 'foo' variable, the header
326       block still correctly accesses the 'title' attribute of the view to
327       which it belongs.  Whenever a view BLOCK is processed, the 'view' vari‐
328       able is always updated to contain the correct reference to the view
329       object to which it belongs.
330
331           [% bar = foo %]
332           [% foo = { title => "New Foo" } %]  # no problem
333           [% bar.header %]                    # => Title: Hello World
334
335       Saving References to External Views
336
337       When it comes to view inheritance, it's always a good idea to take a
338       local copy of a parent or delegate view and store it as an attribute
339       within the view for later use.  This ensures that the correct view ref‐
340       erence is always available, even if the external name of a view has
341       been changed.
342
343           [% VIEW plain %]
344              ...
345           [% END %]
346
347           [% VIEW fancy %]
348              [% view.plain = plain %]
349              [% BLOCK foo %]
350              [% view.plain.foo ⎪ replace('plain', 'fancy') %]
351              [% END %]
352           [% END %]
353
354           [% plain.foo %]         # => <plain>public foo block</plain>
355           [% plain = 'blah' %]    # no problem
356           [% fancy.foo %]         # => <fancy>public foo block</fancy>
357
358       Views as Data Presenters
359
360       Another key role of a view is to act as a dispatcher to automatically
361       apply the correct template to present a particular object or data item.
362       This is handled via the print() method.
363
364       Here's an example:
365
366           [% VIEW foo %]
367
368              [% BLOCK text %]
369                 Some text: [% item %]
370              [% END %]
371
372              [% BLOCK hash %]
373                 a hash:
374                 [% FOREACH key = item.keys.sort -%]
375                    [% key %] => [% item.$key %]
376                 [% END -%]
377              [% END %]
378
379              [% BLOCK list %]
380                 a list: [% item.sort.join(', ') %]
381              [% END %]
382
383           [% END %]
384
385       We can now use the view to print text, hashes or lists.  The print()
386       method includes the right template depending on the typing of the argu‐
387       ment (or arguments) passed.
388
389           [% some_text = 'I read the news today, oh boy.' %]
390           [% a_hash    = { house => 'Lords', hall => 'Albert' } %]
391           [% a_list    = [ 'sure', 'Nobody', 'really' ] %]
392
393           [% view.print(some_text) %]
394                               # Some text: I read the news today, oh boy.
395
396           [% view.print(a_hash) %]
397                               # a hash:
398                                    hall => Albert
399                                    house => Lords
400           [% view.print(a_list) %]
401                               # a list: Nobody, really, sure
402
403       You can also provide templates to print objects of any other class.
404       The class name is mapped to a template name with all non-word character
405       sequences such as '::' converted to a single '_'.
406
407           [% VIEW foo %]
408              [% BLOCK Foo_Bar %]
409                 a Foo::Bar object:
410                     thingies: [% view.print(item.thingies) %]
411                      doodahs: [% view.print(item.doodahs)  %]
412              [% END %]
413           [% END %]
414
415           [% USE fubar = Foo::Bar(...) %]
416
417           [% foo.print(fubar) %]
418
419       Note how we use the view object to display various items within the
420       objects ('thingies' and 'doodahs').  We don't need to worry what kind
421       of data these represent (text, list, hash, etc) because we can let the
422       view worry about it, automatically mapping the data type to the correct
423       template.
424
425       Views may define their own type => template map.
426
427           [% VIEW foo
428                map = { TEXT  => 'plain_text',
429                        ARRAY => 'show_list',
430                        HASH  => 'show_hash',
431                        My::Module => 'template_name'
432                        default    => 'any_old_data'
433                      }
434           %]
435               [% BLOCK plain_text %]
436                  ...
437               [% END %]
438
439               ...
440
441           [% END %]
442
443       They can also provide a 'default' map entry, specified as part of the
444       'map' hash or as a parameter by itself.
445
446           [% VIEW foo
447                map     = { ... },
448                default = 'whatever'
449           %]
450              ...
451           [% END %]
452
453       or
454
455           [% VIEW foo %]
456              [% view.map     = { ... }
457                 view.default = 'whatever'
458              %]
459              ...
460           [% END %]
461
462       The print() method provides one more piece of magic.  If you pass it a
463       reference to an object which provides a present() method, then the
464       method will be called passing the view as an argument.  This then gives
465       any object a chance to determine how it should be presented via the
466       view.
467
468           package Foo::Bar;
469
470           ...
471
472           sub present {
473               my ($self, $view) = @_;
474               return "a Foo::Bar object:\n"
475                    . "thingies: " . $view.print($self->{ _THINGIES }) . "\n"
476                    . "doodahs: " . $view.print($self->{ _DOODAHS }) . "\n";
477           }
478
479       The object is free to delve deeply into its innards and mess around
480       with its own private data, before presenting the relevant data via the
481       view.  In a more complex example, a present() method might walk part of
482       a tree making calls back against the view to present different nodes
483       within the tree.  We may not want to expose the internal structure of
484       the tree (because that would break encapsulation and make our presenta‐
485       tion code dependant on it) but we want to have some way of walking the
486       tree and presenting items found in a particular manner.
487
488       This is known as Structure Shy Traversal.  Our view object doesn't
489       require prior knowledge about the internal structure of any data set to
490       be able to traverse it and present the data contained therein.  The
491       data items themselves, via the present() method, can implement the
492       internal iterators to guide the view along the right path to presenta‐
493       tion happiness.
494
495       The upshot is that you can use views to greatly simplify the display of
496       data structures like XML::DOM trees.  The documentation for the Tem‐
497       plate::Plugins::XML::DOM module contains an example of this.  In
498       essence, it looks something like this:
499
500       XML source:
501
502           <user name="Andy Wardley">
503               <project id="iCan" title="iCan, but theyCan't"/>
504               <project id="p45"  title="iDid, but theyDidn't"/>
505           </user>
506
507       TT View:
508
509           [% VIEW fancy %]
510              [% BLOCK user %]
511                 User: [% item.name %]
512                       [% item.content(myview) %]
513              [% END %]
514
515              [% BLOCK project %]
516                   Project: [% project.id %] - [% project.name %]
517              [% END %]
518           [% END %]
519
520       Generate view:
521
522           [% USE dom = XML.DOM %]
523           [% fancy.print(dom.parse(xml_source)) %]
524
525       Output:
526
527                 User: Andy Wardley
528                   Project: iCan - iCan, but theyCan't
529                   Project: p45 - iDid, but theyDidn't
530
531       The same approach can be applied to many other areas.  Here's an exam‐
532       ple from the File/Directory plugins.
533
534           [% VIEW myview %]
535              [% BLOCK file %]
536                 - [% item.name %]
537              [% END %]
538
539              [% BLOCK directory %]
540                 * [% item.name %]
541                   [% item.content(myview) FILTER indent %]
542              [% END %]
543           [% END %]
544
545           [% USE dir = Directory(dirpath) %]
546           [% myview.print(dir) %]
547
548       And here's the same approach use to convert Pod documentation to any
549       other format via template.
550
551           [%  # load Pod plugin and parse source file into Pod Object Model
552               USE Pod;
553               pom = Pod.parse_file(my_pod_file);
554
555               # define view to map all Pod elements to "pod/html/xxx" templates
556               VIEW pod2html
557                   prefix='pod/html';
558               END;
559
560               # now print document via view (i.e. as HTML)
561               pod2html.print(pom)
562           %]
563
564       Here we simply define a template prefix for the view which causes the
565       view to look for 'pod/html/head1', 'pod/html/head2', 'pod/html/over' as
566       templates to present the different sections of the parsed Pod document.
567
568       There are some examples in the Template Toolkit test suite: t/pod.t and
569       t/view.t which may shed some more light on this.  See the distribution
570       sub-directory 'examples/pod/html' for examples of Pod -> HTML tem‐
571       plates.
572
573       (This documentation is incomplete but I'm not going to get it 100%
574       pefect until the syntax and API stabilise).
575

AUTHOR

577       Andy Wardley <abw@wardley.org>
578
579       <http://wardley.org/http://wardley.org/>
580

VERSION

582       Template Toolkit version 2.18, released on 09 February 2007.
583
585         Copyright (C) 1996-2007 Andy Wardley.  All Rights Reserved.
586
587       This module is free software; you can redistribute it and/or modify it
588       under the same terms as Perl itself.
589
590
591
592perl v5.8.8                       2007-02-09        Template::Manual::Views(3)
Impressum