Dart Templates
As mentioned by Seth Ladd, Dart now has a template system in the bleeding_edge branch. One way to learn what is offered, is to look at the uitest.dart unit test. Since the template code is in flux I’ve created some scripts to help init and build templates. A sample Dart Template Example is provided to follow along with this post. Please keep in mind this is currently subject to change by the Dart team, provide feedback to help the project along.
exportTemplateUtils.sh script is used for exporting all the dependent code from the dartlang code base. The template build script depends on lib, css, and template folders from the utils directory.
[code lang=”shell”]
22:54:59-adam@Adams-MacBook-Air:~/dart/DartTemplateExample
$ ./exportTemplateUtils.sh
A lib
[…]
Exported revision 5635.
A css
[…]
Exported revision 5635.
A template
[…]
Exported revision 5635.
[/code]
The DivisionSales.tmpl was ripped from the unit test and adjusted for the project. The template keyword is used for defining the template name. Inside the template you can have css, html and scripting. Dart team is currently experimenting with the following.
[code lang=”html”]
template DivisionSales(var divisions) {
css {
.division-item {
background-color: #bbb;
border-top: 2px solid white;
line-height: 20pt;
padding-left: 5px;
}
.product-item {
background-color: lightgray;
margin-left: 10px;
border-top: 2px solid white;
line-height: 20pt;
}
.product-title {
position: absolute;
left: 45px;
}
.product-name {
font-weight: bold;
position: absolute;
left: 100px;
}
.product-users {
position: absolute;
right: 150px;
font-style: italic;
color: gray;
width: 110px;
}
.expand-collapse {
margin-left: 5px;
margin-right: 5px;
vertical-align: top;
cursor: pointer;
}
.expand {
font-size: 9pt;
}
.collapse {
font-size: 8pt;
}
.show-sales {
display: inherit;
}
.hide-sales {
display: none;
}
.sales-item {
font-family: arial;
background-color: lightgray;
margin-left: 10px;
border-top: 1px solid white;
line-height: 18pt;
padding-left: 5px;
}
.ytd-sales {
position: absolute;
left: 100px;
}
}
<div>
${#each divisions}
<div class="division-item">
<span>${name}</span>
<span> - </span>
<span>${id}</span>
</div>
<div>
${#each divisions.products}
<div class="product-item">
<span var=productZippy class="expand-collapse expand">▼</span>
<span class=’product-title’>Product</span>
<span class="product-name">${name}</span>
<span class="product-users">${users} </span>
<div class="show-sales">
${#each products.sales}
<div class="sales-item">
<span>${country}</span>
<span class="ytd-sales">${yearly}</span>
</div>
${/each}
</div>
</div>
${/each}
</div>
${/each}
</div>
}
template Header(String company, Date date) {
css {
.header {
background-color: slateGray;
font-family: arial;
color: lightgray;
font-weight: bold;
padding-top: 20px;
}
}
<div class=’header’ align=center>
<h2>${company}</h2>
<div align=right>${date}</div>
</div>
}
[/code]
The scripting is very basic at the moment. Looking at the tokenkind.dart one can get an idea of what is supported.
[code lang=”java”]
[…]
// Synthesized tokens:
static final int END_NO_SCOPE_TAG = 50; // />
static final int START_EXPRESSION = 51; // ${
static final int START_COMMAND = 52; // ${#
static final int END_COMMAND = 53; // ${/
static final int EACH_COMMAND = 53; // ${#each list}
static final int WITH_COMMAND = 54; // ${#with object}
static final int IF_COMMAND = 55; // ${#if (expression)}
static final int ELSE_COMMAND = 56; // ${#else}
[…]
[/code]
buildTemplates.sh script will loop over all *.tmpl files in the current working directory and generate *.dart files for each one.
[code lang=”shell”]
22:57:41-adam@Adams-MacBook-Air:~/dart/DartTemplateExample
$ ./buildTemplates.sh
Building dart templates
Parsed /Users/adam/dart/DartTemplateExample/DivisionSales.tmpl in 3134 msec.
Codegen /Users/adam/dart/DartTemplateExample/DivisionSales.tmpl in 215 msec.
Wrote file /Users/adam/dart/DartTemplateExample/DivisionSales.dart in 215 msec.
Copy & Paste import statements
#source(‘DivisionSales.dart’);
[/code]
After the dart code is generated the following source statements can be copied into the main/lib.
[code lang=”javascript”]
#import(‘dart:html’);
#source(‘DivisionSales.dart’);
class Sales {
String country;
String yearly;
Sales(this.country, this.yearly);
}
class Products {
List<Sales> sales;
String name;
String users;
Products(this.name, this.users, this.sales);
}
class Divisions {
List<Products> products;
String id;
String name;
Divisions(this.id, this.name, this.products);
}
class DartTemplateExample {
DartTemplateExample() {
}
void run() {
document.body.elements.add(new Header("Dollar Shave Club", new Date.now().toString()).root);
List<Sales> sales = [new Sales("USA", "3500"), new Sales("USA", "4500")];
List<Products> products = [new Products("Razor", "Sammy", sales)];
List<Divisions> divisions = [new Divisions("South West", "A-Team", products), new Divisions("North East", "B-Team", products),];
DivisionSales divisionSales = new DivisionSales(divisions);
document.body.elements.add(divisionSales.root);
}
}
void main() {
new DartTemplateExample().run();
}
[/code]
This example is deployed on github. You can also experiment with the template system to see what code gets generated on a live page. At first glance the template system is simple enough to use, I would assume things would change in the future. For now the Dart team has provided enough for people to start banging away and provide feedback.