When creating web applications I like to extract common pieces of mark-up into helper functions. I use Hasic which means helper functions are just simple VB functions that return XElement objects.
However, dynamic web pages often use javascript to add elements at runtime. Consider a page with a table of data which has an form to add rows. We want to add rows without reloading the whole page. So we use AJAX to post the new data, then, in javascript, create the new table row and append to the table.
So we have a repetition of the same HTML template; server-side and client-side.
Using Hasic we can eliminate this repetition. The following class field defines an HTML template:
Shared customerRow As New HtmlTemplate(Of String, String)("customerRow", Function(first, last) _
<tr>
<td><%= first %></td>
<td><%= last %></td>
</tr>)
Let’s break this down. We are creating an HTML template that takes two string arguments and returns an XElement. We have named it “customerRow” and given a lambda expression that returns the HTML. That second argument is an Expression(of Func(of String, String, XElement)). So the HtmlTemplate is able to parse the expression tree and generate an equivalent javascript function.
Within my page (server-side) I can use the template like a function (by using an indexer property).
Protected Overrides Function Contents() As XElement
Return _
<_>
<table id="customers">
<tr><th>First name</th><th>Last name</th></tr>
<%= customerRow("Andrew", "Davey") %>
<%= customerRow("John", "Smith") %>
</table>
<div>
<button id="add">Add Row</button>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<%= InlineJavascript(customerRow.Javascript) %>
<script type="text/javascript">
$(function() {
$('#add').click(
function addRow() {
$('#customers').append(customerRow('John','Smith'));
}
);
});
</script>
<_>
End Sub
The above code also includes the javascript for the page. Notice the customerRow.Javascript property. This returns the javascript function as a string. InlineJavascript is a helper that wraps up the javascript into a CDATA making the angle brackets safe. The javascript function looks like this:
function customerRow(first,last) {
return '<tr><td>' + last + '</td><td>' + first + '</td></tr>';
}
The name of the function is what we gave to the HtmlTemplate constructor. Concat-ing strings may not be the best way, but it works for this prototype.
I hope you can see the value here. The template function is written only once. DRY win :)