ucwTutorialIntroducingTal

ucw Tutorial

Getting Tal into play

Welcome back to this tutorial and journey into UCW and all such stuff ;-) As pointed out I'm really running short on time, so this may be not the most elaborated stuff I'll write.

Separation of concerns

Till now we just have used Common Lisp in all our examples. We wrote a class or component, wrote a specialiced render method on this and we acted on it in some sort of action.

One can argue however that we did not have separated the view part from the "controller" part. Now this is fine if you are used to Common Lisp (so probably fine for all of you ;-), but hardly for a larger audience. For most Common Lisp is an alien. And especially for web "Designer", that are those you add funky layout (or not so funky ones) to you pages, it's no-where land. So how can we break out of it?

Tal to the rescue.

Now this part of UCW is even less documented then anything else. I just invite you to try the following simple thing. Display a form to the user, from a tal template....

Or stay tuned and follow this pages ;-)

The example

Well I just want to try to show you the mentioned simple thing. Just display form (be it well-formed or not) and see how it may work. First burden, how do I inform UCW that a page should be rendered by TAL template.

You have to check the examples or doc strings quite careful. You can find something here or try you luck with

(apropos "template" :ucw) 
and there you'll find something. Now you just have to see that you include 'TEMPLATE-COMPONENT' into the parent list of you class.

The UCW examples use this pattern (slighly modified for the example here")

(defclass tal-test (simple-window-component template-component)
  ((val-1 :accessor val-1 :initform (make-instance 'string-field
                                   :input-size 20
                                   :validators (list (make-instance 'not-empty-validator)))) 

(val-2 :accessor val-2 :initform (make-instance 'string-field :input-size 20 :validators (list (make-instance 'not-empty-validator))))) (:metaclass standard-component-class) (:default-initargs :template-name "tal/tal-test.tal" :title "UCW Tutoial TALitations"))

I added the SIMPLE-WINDOW-COMPONENT because I liked to get the proper heading for a valid xhtml page, which are added by including this part.

As you can see I used the same :INITFORM as before.

What is new is the :TEMPLATE-NAME argument. This tells which component is responsible for rendering this class.

How TAL files look

finding out about TAL is not an easy undertaking. I just was happy enough to find something in the examples. TAL and its macro language METAL were invented as part of the Python Zope Framework, and more extensive documentation on TAL is available at the Zope site.

Here's now our first TAL Template

< div xmlns:tal="http://common-lisp.net/project/bese/tal/core"
     xmlns:ucw="http://common-lisp.net/project/ucw/core"
     tal:in-package="ucw.tutorial">

< h1>To TAL or not < form method="POST" ucw:action="(tal-test-viewer $component)">

< ucw:render-component ucw:component="(val-1 $component)"/> < ucw:render-component ucw:component="(val-2 $component)"/>

< input type="submit"/>

< /form>

< /div>

ATTENTION: I added a blank between < and opening or closing tag otherwise the rendering failed.

The first two entries define the XML name space (xmlns). If you follow those URL's you'll see the definition of which tags and attributes are legal in a UCW TAL file, and in what context. It's not quite documentation, but useful since essentially these xmlns files are source code and they tell the XML parser how to read the TAL file.

The next part is easy. I just check that I'm working in the proper package to access the embedded lisp stuff without the need to qualify things.

The embedded lisp can be found as a string behind special tags.

There must be quite few others. I hope I'll find them at the proper time. A few parts have names starting with '$', $COMPONENT stands for the currently active component.

This TAL page renders the class TAL-TEST, so we have to write an function to act on this part. So here we go:

(defaction tal-test-viewer ((form tal-test))
  (call 'tal-test-viewer :data form))

This is "business-as-usual". I wrote the following class to render the result:

(defcomponent tal-test-viewer (simple-window-component)
  ((data :initarg :data :accessor data)))

(defmethod render ((win tal-test-viewer)) (<:p "val-1 = " (<:as-is (value (val-1 (data win))))) (<:p "val-2 = " (<:as-is (value (val-2 (data win))))))

Now it could have been possible to use another template for this task, as you would expect in a surrounding where View and Controller are more clearly separated. Agreed it's nested a bit deep, but improving that is not really hard.

But how do I start displaying a component implemetend by a TAL template

Well this is what I found. You can call it as if there would be a normal render method. So you start viewing the first page this way:

(defentry-point "index.ucw" (:application *ucw-yaml-test-application*) () (call 'tal-test))

Flow of control

Now we see how the things go through TAL, UCW and Common Lisp.
  1. One implements some class If this class has to rendered by a TAL template one includes TEMPLATE-COMPONENT in the parent list
  2. Then you start the display chain in the usual way, you call CALL on the compoment to display. If this component takes initialization arguments then of course the dialogs to get the information for thi arguments ar called first
  3. If you have template, this template is "called", otherwise the proper specialied RENDER method
  4. Within the template is it possible to "call-back" into lisp. This is done via special ucw form tags or special tal parameters
  5. If you have a form in the template you declare the action to be carried out after submitting the form with the UCW:ACTION special tag. This then calls the proper DEFACTION method
  6. From there on this steps get repeated.

Calling out from Lisp to TAL Templates

Well this stuff was somewhat lost so let's readd it. There are two ways to call out from Lisp to TAL files