Take full advantage of CoffeeScript in your templates. hamlet doesn’t use a crippled templating language and supports embedding arbitrary CoffeeScript expressions. Write expressive, intuitive templates that can be understood at a glance.
Compared to Backbone , hamlet is much less verbose. Using hamlet, you’ll never have to set up handlers or manually sync state between your model and the DOM. Eliminating this entire class of application code reduces complexity and improves maintainability.
npm install hamlet.coffee
Usage
The template language draws on the original old school Ruby HAML template language (Hamlet… get it?). For those of you that have experience with HAML or JADE , you will feel right at home.
Here’s what a typical hamlet template looks like:
-th = ["Category", "Product", "Price", "Quantity", "Subtotal", ""]
%table
%thead
%tr
- each th, (name) ->
%th= name
%tbody
- each @lines, ->
%tr
%td.category
%select(options=@categories value=@selectedCategory)
%td.product
%select(options=@products value=@selectedProduct)
%td.price= @price
%td.quantity
%input(type="number" value=@quantity)
%td.subtotal= @formattedSubtotal
%td.remove
%a(href="#" @click) Remove
%hr
.sum
Total value:
%span.total= @formattedTotal
%button(click=@addLine) Add product
%button(click=@submitOrder) Submit order
You can see that it flows really well with CoffeeScript. In addition to basic templating functionality hamlet also provides browser specific features like basic data binding and event handler wire up.
The context object for the template above:
nullCategory = {name: "Select...", value: -1, products: []}
nullProduct = {name: "Select...", value: -1, price: 0}
categories = Observable [nullCategory].concat data.categories
Line = ->
self =
categories: categories
selectedCategory: Observable(categories()[0])
quantity: Observable(1)
subtotal: Observable(0)
price: ->
@selectedProduct().price
products: ->
[nullProduct].concat(@selectedCategory().products)
selectedProduct: Observable(nullProduct)
subtotal: ->
@price() * @quantity()
formattedSubtotal: ->
"$" + @subtotal().toFixed(2)
toJSON: ->
if @selectedProduct()
{ productName: @selectedProduct(), quantity: @quantity() }
click: (e) ->
e.preventDefault()
lines.remove(self)
self.selectedCategory.observe (category) ->
self.selectedProduct(nullProduct)
self
lines = Observable([Line()])
model =
addLine: ->
lines.push(Line())
lines: lines
submitOrder: ->
json = JSON.stringify lines.map (l) ->
l.toJSON()
alert("Could now send this to server: " + json)
total: ->
sum = lines.reduce (total, line) ->
total + line.subtotal()
, 0
formattedTotal: ->
"$" + @total().toFixed(2)
What else?
You can play with interactive examples on the hamlet.coffee site and see feature equivalent code for a few other frameworks.