[Bese-devel] How to use tal-templates
Marco Baringer
mb at bese.it
Mon Aug 15 05:46:45 UTC 2005
Marco Simon <marco_simon at web.de> writes:
> could somebody please give me short "hello world" on how to use the
> tal-template engine?
> I thought it would be as easy as declaring an component with the
> super-class "template-component" and a template-name, but that
> seemed not to be enough.
> I even had a look at Marco Baringers's "counter" example which uses
> the tal-template mechanism - but didn't manage it. So could you
> please give me some example-lines which show how to implement *.tal
> - files ?
using a tal template requires that 1) we create the .tal file and 2)
we tell ucw haw to find it.
#1 is, i hope, obvious, #2 requires that we pass :template-name as an
initarg when creating the component (most of the time, but not always,
you'll use the class option :default-initargs) and setting up the
proper tal-generator. a tal-generator is an object which, given a
template filename, returns a function which, given a tal evironment,
actually prints the page to *yaclml-stream*. at some point i planned
on having multiple types of tal-generators, for now all we have is the
file-system-generator, and i don't think we need more. every
application has its own generator (which is _not_ tied to the single
component), this lets use the same component with different templates
in different apps (though the same component with differnt templates
in the same app will require multiple component classes).
(defvar *example-application*
(make-instance 'cookie-session-application
:url-prefix "/ucw/examples/"
:tal-generator (make-instance 'yaclml:file-system-generator
:cachep t
:root-directories (list *ucw-tal-root*))
:www-roots (list (merge-pathnames "./ucw/examples/" *ucw-tal-root*))))
that's the form whcih creates the example application object, notice
the :tal-generator keyword. file-system-generator has a list of
directories, in this case just *ucw-tal-root*, which it uses to search
for the actually template file. if our file-system-generator has
"/foo/" on its list of root-directories and we're looking for a
template named "here/there/whatever.tal" it will load the file at
"/foo/here/there/whatever.tal".
in the case of the counter example the template is named
"ucw/examples/counter.tal" and the root-directories of the example
app's generator is just (list "/path/to/ucw/wwwroot/") hence
counter.tal needs to live at
"/path/to/ucw/wwwroot/ucw/examples/counter.tal".
does this make sense?
once we've found the template we need to actually use it. all tal
templates are eventually converted to lisp code and use yaclml macros
underneath, with some extensions. when you use an anchor tag in a tal
file (if you've setup the xmlns properly) you'll eventually "run" the
<:A macro, when you see <ucw:option value="foobar">blah
blah</ucw:option> that is exactly the same as (<ucw:option :value
"foobar" "blah blah blah") in regular lisp code. the tal attribute
extensions are (or should be) documentated somewhere, here's a quick
summary:
Attributes:
tla:content="(something)" - (SOMETHING) is evaluated to produce a
string and that is used as the body of the tag.
tal:replace="(something)" - the entire tag (including all attributes)
is replaced with the string returned by (SOMETHING).
tal:dolist="(something)" - (SOMETHING) returns a list of tal
environment objects (which are themselves lists of alists, clos
objects or hash tables). the body of the tag is executed once for each
environment object returned by (SOMETHING), the current env is
extended with that environment.
tal:in-package="package-name" - The package ti use for evaluating
code, interneing names, etc.
Tags:
<tal:tal> - does nothing in and of itself, but it provides a place to
put tal:attributes when you don't want to add another tag. <div> or
<span> should work just as well but browsers aren't perfect.
<tal:include> - include another tal template.
tal:name="whateverl.tal" - the name of the of the file to include (not
evaluated). the file is found using the same mechanism as described
above.
param:xyz="(something)" - something is evaluated and its return
value (a list object) is put into included file's environment under
the name xyz. (xyz is converted into a symbol in the current tal
package).
<param:xyz> ... </param:xyz> - xyz is bound to the _string_ which
the body of the tag produces.
Other things:
tal attributes are normally evaluated. there is a read macro bound to
#\$ which will lookup in the current env the value associated with the
symbol. So $whatever in a tal attribute correspands to the value of
the lisp object bonud to the name whatever (whatever is a symbol in
the current tal package (see tal:in-package above)).
non tal attributes are generally strings which are left alone. the
exception is if the contain ${ ... } or @{ ... }. in this case the
body of ... is evaluated it it's return value (a string in the case of
$, a list of strings in the case of @) is substituted for the text
occupied by the ${ ... } code. example:
<table tal:in-package=":it.bese.ucw-user">
<!-- all symbols, etc will be interned into the :it.bese.ucw-user
package -->
<tr tal:dolist="$rows">
<!-- loop over the tal env bound to ROWS
<td style='background: #${ (if $even-row "000000" "333333") };"
tal:content="$row-value">
<!-- even rows get a white background, odd rows get a light gray
background. this text inside the ttag will be replace
with the value associated with $body -->
dummy value goes here
</td>
</tr>
</table>
hth.
p.s. - this is the way things _should_ be. i haven't done a lot of tal
coding lately so there may be deviations (which are bugs and sholud be
reported as such).
--
-Marco
Ring the bells that still can ring.
Forget the perfect offering.
There is a crack in everything.
That's how the light gets in.
-Leonard Cohen
More information about the bese-devel
mailing list