Flapjax Templates

The response to the template language in Flapjax has been mixed, to say the least. The most common complaint is that they mix content with style. True — this can be done with our templates. But nothing stops a developer from putting CSS in the HTML directly. Nothing except good sense, that is.

In response to a recent post on our discussion group for Flapjax, I wrote about this briefly:

…the only compiler specific syntax is the templates: curly-bang — {!, !} and triple-stick — |||. But these are parsed out of HTML PCDATA and attribute nodes, so a JavaScript/Flapjax programmer needn’t consider them. We introduced the syntax as a way to reduce the clutter of “insertDomB” and “insertValueB” calls. For example, the template language is:

It's been {! currentSeconds ||| (loading...) !} seconds since the beginning of 1970, and it's all been downhill.

while we must write the following without it:


It's been (loading...) seconds ... .

This can become a huge mess, so the templates simplify it. We wouldn't want to encourage doing all of your computation in the display layer! I'd compare it to Smarty or JSP -- while you can include complex computations in the tags, it's meant only to ease the interface between models in code and presentations on screen.

I think that soundly characterizes the template language. Shriram wants that in the tutorial, so that'll show up there eventually. (Some people take classes during the semester, but the Flapjax team has much more important things to do. Or so we're told.) But it would be a big mistake to see Flapjax as providing just that -- the functional reactivity is the interesting bit.


Tonight we're presenting the language to the undergraduates in the DUG; there's an exciting contest announcement coming up, as well. Who has time for midterms?

9 Comments

  1. My beef with templating – here and in most other systems – is difficulty in specifying where the data comes from.

    One should be able to cut a chunk of template out and abstract it.

    As we’re in a position to provide this sort of approach, I think we should do it and let naysayers shove it and depend on the current approach of convoluted advice systems with callbacks.

  2. I’m not sure what you mean by “where the data comes from”. Like I said over lunch, I advocate using only variable names in templates. Programmers design an interface of exported variables and designers can then say, “put the dynamic value FOO here”.

    As for abstraction, I think that should all take place in the code, not in the template itself. In fact, my thesis is that a succinct bidirectional specification (‘program’) of the presentation structure (along with functional reactive programing) is sufficient to connect the model to the view, i.e. act as a controller. In this case, templates aren’t necessary at all.

  3. >> Programmers design an interface of exported variables and designers can then say, “put the dynamic value FOO here”.

    Yes, if by exported variables you mean variables to be shared between a template instantiation and whatever code instantiated/embedded it. This interface is what I mean by allowing abstraction over templates: a widget template should be explicitely parameterized. The theory of lenses is orthogonal to templates, but I think most data passed into a template would be best described with lenses. I haven’t had a chance to read Pierce’s ~60 page report yet but the idea seems intuitive – I may be way off base.

    >> As for abstraction, I think that should all take place in the code, not in the
    template itself.

    I do not know what you mean – I view the template as most of the code, with helper functions for describing the data relationships (the lenses) and animations (frp). I am interested in describing the smallest templates (for example, a display list) and then combining their instantiations into bigger templates, such as two lists sharing their data and styled extended with some externally defined animations.

    It will be interesting to see when lenses would be more appriate than frp, more specifically in the gap between what I have been calling data relationships and animations.

    The race is on: me with adding basic FOL style operators to frp for defining animations (a looser letrec) and you for lenses :) It will be kick ass if even just one of us delivers :)

  4. I should have been more clear: by template, I meant the {! !} include syntax we have. I would only use them as a marker for where a lens’ output should appear.

    In your sense of “template as widget”, I’m not sure how lenses and templates are different at all. Lenses, in my proposed system, would be model-to-view isomorphisms. Any intervening “template” which expanded a view element to a more complicated view element could be nothing other than a lens — how else would be extract the data? So to say they’re orthogonal doesn’t even compute for me.

    I am excited to see how the lens work will interact with animation. I’m not sure what attributes/elements an animation will need to affect; I think so long as id attributes are left alone, the lens system will be happy.

    The race is on indeed! And it is of epic, Deathrace 2000 proportions. Call me Thomasina Paine.

  5. Ah we talking about different things. I’m talking about something closer to modules, but whose contents are just templated code:

    (module ‘fisheye’ (header : htmlb, buttons : list htmlb)
    {! header !}
    {! button !})

    or some similarly eye-gauging syntax. ‘buttons’ in the above case would naturally be a Behaviour, but what happens when we are describing a list with dragable items? Hello lenses.

    It’s simple, obvious, and grunt work – but stops one of the biggest complaints against templating: the loss of modular reasoning.

    Just be careful not to Crash (http://www.imdb.com/title/tt0115964/) – my lingering memory of Preston.

  6. Modules with templated code? Sounds like a function to me. You would say something like fisheye(headerB, listOfButtonsB), which would be a lens. Of course, if there’s no data to read out, it’s a boring lens, but so it goes.

    What does Crash have to do with Preston of the unending opinions?

  7. >>Modules with templated code? Sounds like a function to me.

    Yep.

    >> Of course, if there’s no data to read out, it’s a boring lens, but so it goes.

    How would it be clear what data the fisheye provides? I think it should be made explicit, rather than being pulled out of a returned dom node,
    which is why I said module (not sure about state implications), though a return of a record would work superficially:

    (module ‘fisheye’ (header : htmlb, buttons : list htmlb) (iconSize : number)
    div(header, input({id: iconSize} /* lense magik */), map ( x -> div(x), buttons)))

    x = fisheye(div(), (div(), div())) /* record: x.domNode, x.iconSize */

    >> What does Crash have to do with Preston of the unending opinions?

    Reminded me of one of the opinions he exposed to me, some reason I thought you were there to witness it.

    You need a preview button :)

  8. Well the fisheye lens has concrete domain { header: html, buttons: [ html ] } and an abstract range of fisheye div structures. Note that all fisheye does is alter structure: the concrete model gets converted into a DOM subtree.

    In my system, you should be able to build up fisheye as a bidirectional program itself. (This is pretty easy, since DIV(attributes, [ html ]) and all of the other element constructors can easily be lenses!) In that case, it would be compositionally derivable that fisheye introduces no new data to the model.

    So I don’t fully understand your problem, or what you mean by “[the] data the fisheye provides … should be made explicit, rather than being pulled out of a returned DOM node.” What do ‘data’, ‘explicit’, and ‘returned’ mean? I have the feeling that explaining my lens driver — the system which decides when to get and putback — would clarify things.

  9. the inability to inline JS with HTML has always been a royal PITA. i recently started a client side javascript templating engine that relies on a js pre-proessor to parse out any inlined html into the JS script itself. you’ve got a similar thing going on here. i was pretty amazed how easy it was to write. my boo preprocessor is just shy of 250 lines, albiet theres a lot of error checking i dont do (mostly related to handling of arguments and file manipulation, the processing itself is fairly minimal/safe).

Leave a Reply

Your email address will not be published. Required fields are marked *