This post is a part of a series:
Mimeo's token building API supports a block token that can repeat or enclose content. It creates a new section with an exclusive set of tokens. The block tokens are delimited by an identifier and a terminator. Its type context is a member of the current model whose return type is IEnumerable<TChild>. The new context for each block iteration will be the type of TChild.
In the last post, we defined a Person class.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
Let's amend Person, adding a collection of orders.
public IEnumerable<Order> Orders { get; set; }
Here's the order class:
public class Order
{
public int Id { get; set;}
public decimal Amount { get; set;}
public DateTime DateSubmitted { get; set; }
}
Before, we used a builder to tokenize members of the Person class. Now, we'll be creating a block for Person.Orders, which will have its own builder context. The block will be rendered for each Order in the collection.
builder.Block(p => p.Orders, "@Orders", order =>
{
order.Tokenize(o => o.Amount.ToString("c"), "@Amount");
order.Tokenize(o => o.DateSubmitted.ToShortDateString(), "@DateSubmitted");
}).EndsWith("@EndOrders");
The builder creates a block that starts with "@Orders" and ends with "@EndOrders". The token identifiers are just delimiters, serving no other purpose. The context parameter (order) is a new token builder for an Order object. Inside of this context, members of the Order class can be tokenized. This example shows how the properties Amount and DateSubmitted are tokenized.
Tokens are not visible outside of their immediate scope. For example, if you wanted to put the person's name inside of the block, you would have to add their name to the Order, or make Person a property on Order and access Order.Person.FirstName. Improvement in this area could be a feature down the road.
With the block token added to our stencil, let's take a look at what a sample template could look like.
==========
@FirstName @LastName is a Person who is @Age years old.
Submitted On | Amount
@Orders
@DateSubmitted | @Amount
@EndOrders
==========
As you might expect, the tokens for Amount and DateSubmitted are used between the block identifiers @Orders and @EndOrders. Here's some sample output:
==========
John Nelson is a Person who is 24 years old.
Submitted On | Amount
1/1/2011 | $10.00
1/2/2011 | $20.00
1/3/2011 | $30.00
==========
It is worthwhile to note that the templates preserve 100% of whitespace. This isn't generally too much of a problem, but it has potential for making the template look crazy in scenarios where whitespace is important. I designed this library with the intention of generating HTML, which is much less whitespace intensive.
Here is a complete listing of the sample code in this post:
using System;
using System.Collections.Generic;
using Mimeo;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
const string template = @"==========
@FirstName @LastName is a Person who is @Age years old.
Submitted On | Amount
@Orders
@DateSubmitted | @Amount
@EndOrders
==========";
var mimeographs = new Mimeographs();
var mimeograph = new Mimeograph<Person>(builder =>
{
builder.Tokenize(p => p.FirstName, "@FirstName");
builder.Tokenize(p => p.LastName, "@LastName");
builder.Tokenize(p => p.Age.ToString(), "@Age");
builder.Block(p => p.Orders, "@Orders", order =>
{
order.Tokenize(o => o.Amount.ToString("c"), "@Amount");
order.Tokenize(o => o.DateSubmitted.ToShortDateString(), "@DateSubmitted");
}).EndsWith("@EndOrders");
});
mimeographs.Add(mimeograph);
mimeographs.CreateStencil<Person>("person-template", template);
var person = new Person
{
FirstName = "John",
LastName = "Nelson",
Age = 24,
Orders = new List<Order>
{
new Order { Amount = 10m, DateSubmitted = new DateTime(2011,1,1)},
new Order { Amount = 20m, DateSubmitted = new DateTime(2011,1,2)},
new Order { Amount = 30m, DateSubmitted = new DateTime(2011,1,3)}
}
};
var result = mimeographs.Render("person-template", person);
Console.WriteLine(result);
Console.ReadKey();
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public IEnumerable<Order> Orders { get; set; }
}
public class Order
{
public int Id { get; set; }
public decimal Amount { get; set; }
public DateTime DateSubmitted { get; set; }
}
}