1Template::Manual::ViewsU(s3e)r Contributed Perl DocumentaTteimopnlate::Manual::Views(3)
2
3
4
6 Template::Manual::Views - Template Toolkit views (experimental)
7
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
577 Andy Wardley <abw@wardley.org>
578
579 <http://wardley.org/⎪http://wardley.org/>
580
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)