I started playing with NHaml
lately for sheer curiosity. It comes with MVCContrib and
that's what I've been using to explore it.
I'm not completely on board yet that
you'll want to write all your views, for all kinds of application scenarios using NHaml. I know someone will probably
jump out and say that their entire site was built with NHaml and it's wonderful. I'm sure it can be done,
I'm just still wondering if it's more trouble than necessary. On the other hand, if you are starting a new
application from scratch (i.e. you are not inheriting any existing template or that sort of thing,)
then NHaml can guide you through a different way of thinking about your views and simplify them a lot.
I might have already said this before, but I'm generally in favor of working as close to the platform as
possible and viable. That's why I'm not a big fan of things like Script#,
RJS,
and Volta.
NHaml is almost in the same category but it does bring some nice things to the table and that's why I'm not ready
to dismiss it just yet. Just take a look at what our HTML looked like circa 1998 and what it is now with richer
CSS and JavaScript.
As much as I can, I try to separate my (X)HTML from my CSS and my JavaScript. Sometimes it
gets to the point that I wonder why I am using HTML to begin with — it's all data and
structure. I wonder how long until we have a WikiText or MarkDown view engines.
NHaml fits well for these kinds of well-separated HTML views. It does away (kind of) with the HTML tags and
focus on the structure and meaning of each piece of information. Because it defines structure
in a way that works well with CSS, it also works great with jQuery for our JavaScripts. It's
unobtrusive JavaScript heaven!
I think the key to learning NHaml is forgetting about HTML and its tags (or at least don't focus on them).
Forget that the page ultimately rendered will be in HTML. For a moment just visualize the areas of the page
as meaningful pieces of data: sidebar, lists, headings, article title, article body,
author name, navigation tabs, etc, not divs, tables, spans, fieldsets, etc.
Less Noise More Content
The most obvious impression you get when looking at a NHaml template for the first time
is how skinny it is compared to any tag-based template. Your eyes are used to look for
angle brackets to help you understand the structure of the document, but in NHaml
the indentation serves that purpose.
Take a look at a common template to create a grid of products in ASPX.
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title><%= ViewData["pagetitle"] %></title>
</head>
<body>
<h1>All Products</h1>
<table class="grid" id="products">
<tr>
<th>ID</th>
<th>Name</th>
</tr>
<% foreach(var prod in (IEnumerable<Product>)ViewData["products"]) { %>
<tr>
<td><%= prod.ID %></td>
<td><%= prod.Name %></td>
</tr>
<% } %>
</table>
<input type="button" value="Say Hi" onclick="alert('Hi');" />
</body>
</html>
Now take compare that to the NHaml version.
!!! XML
!!!
%html
%head
%title= ViewData["pagetitle"]
%body
%h1 All Products
%table.grid#products
%tr
%th ID
%th Name
- foreach(var prod in (IEnumerable<Product>)ViewData["products"])
%tr
%td= prod.ID
%td= prod.Name
%input{ type="button", value="Say Hi", onclick="alert('Hi');"}/
Never Forget a Closing Tag Again
Having meaningful indentation brings the common advantage of needing to explicitly mark
the end of a block, making that automatic. In other words, the closing tags are added
at the right places for you. That's something I value a lot.
Identifiers and Selectors, Css-Friendly
By now, after looking at the above NHaml sample a few times, you probably
noticed that the class and id attributes are set using
a dot and a # sign, respectively.
%table.grid#products