Skip to content

Instantly share code, notes, and snippets.

@johnbender
Created April 4, 2010 14:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnbender/118dc4cd9d8223c33f63 to your computer and use it in GitHub Desktop.
Save johnbender/118dc4cd9d8223c33f63 to your computer and use it in GitHub Desktop.

While I don't have any hands on experience with Lift's approach to templating it looks a lot like asp.net databinding/templates and from my experience with that toolset it ends up being a cumbersome solution to the problem of separating controller and view. I don't necessarily think mixing code into your views is the "one true way" either, but what you sacrifice in controller code clarity seems to outweigh any gains from separating the two so strictly.

As an example from http://liftweb.net/docs/getting_started/mod_master.html#x1-130002.7 :

<lift:TD.list all_id="all_todos"> 
 <div id="all_todos"> 
 <div>Exclude done <todo:exclude/></div> 
 <ul> 
  <todo:list> 
    <li> 
     <todo:check><input type="checkbox"/></todo:check> 
     <todo:priority> 
       <select><option>1</option></select> 
     </todo:priority> 
     <todo:desc>To Do</todo:desc> 
    </li> 
  </todo:list> 
 </ul> 
 </div> 
</lift:TD.list>

private def doList(reDraw: () => JsCmd)(html: NodeSeq): NodeSeq = 
 toShow. 
 flatMap(td => 
   bind("todo", html, 
    "check" -> ajaxCheckbox(td.done, 
             v => {td.done(v).save; reDraw()}), 
    "priority" -> 
    ajaxSelect(ToDo.priorityList, Full(td.priority.toString), 
             v => {td.priority(v.toInt).save; reDraw()}), 
    "desc" -> desc(td, reDraw) 
    ))

In the above you'll notice that the bind has direct reference to elements in the template, so I think its fair to say you've moved some of your template mixing from view to the controller. From the docs

"This method calls toShow to get the list of to-do items to show. Using the flatMap method, we iterate over each to-do item and binding the item to the incoming html."

In addition I think the result is something thats harder for people to grok. When reading loops and control flow constructs from a programming language in a template its immediately familiar. When binding data into a template, at the very least, the code you need to reference exists in two separate places but interacts very very intimately.

Again, I'm not saying that the current practice of writing code into the template should be the final solution. You could make the case that Haskell is better at parsing and handling text for whatever purpose (databinding or otherwise) than almost any other language and that, as a result, it would be better equipped to handle controller side manipulation of xhtml. In addition this might allow you to better leverage the type system.

Personally I think if your going to be mucking around with html/xhtml a bit of haskell won't make it much worse :D

All,

To contribute something positive here, I would really like to see HAML become the goto template system of choice for haskell web dev if only because the syntax meshes well (indentation, terseness) and there's an enormous sea of web developers already familiar with its use and best practice. One less thing to worry about when learning webdev in haskell.

Best

John

Disclaimer: I am an experienced web developer but I'm relatively new to Haskell. If there is some aspect of the language, unknown to me, that makes the Lift templating/databinding system much more effective feel free to ignore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment