Document Templates
Table of Contents
- Introduction
- Setting Up the HTML Structure
- Adding CSS Styles
- Creating the Template Content
- Data Binding Basics
- Handling Null References
- Conditional Rendering
- Looping and Iterating
- Formatting Numbers
- Displaying Dates
- Working with Currencies
- Creating Tables for Data
- Advanced Techniques
- Sample JSON Data
- Complete Template Example
- Best Practices and Tips
Introduction
This guide provides a comprehensive overview of creating document templates. We'll cover everything from basic structure to advanced formatting techniques, using a freight quote template as our primary example.
Setting Up the HTML Structure
Start with a basic HTML structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Freight Quote</title>
<style>
/* CSS styles will go here */
</style>
</head>
<body>
<!-- Template content will go here -->
</body>
</html>
Adding CSS Styles
Include internal CSS styles to format your document:
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.header {
text-align: center;
margin-bottom: 20px;
}
.company-info {
margin-bottom: 20px;
}
.order-info {
border: 1px solid #ccc;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.info-box-title {
font-weight: bold;
margin-bottom: 10px;
font-size: 18px;
}
.section {
margin-bottom: 20px;
}
.info-box {
border: 1px solid #ccc;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.info-box-content {
margin-top: 10px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
th,
td {
border: 1px solid #ccc;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
.terms-and-conditions {
font-size: 0.9em;
margin-top: 30px;
}
.signature {
margin-top: 40px;
}
</style>
Creating the Template Content
Use jsrender syntax to create dynamic content. Here's an example of the document structure:
<div class="header">
<div class="company-info">
<h1>{{:organization.companyName}}</h1>
{{:organization.addressLine}}<br />
{{:organization.cityName}}, {{:organization.stateCode}}
{{:organization.postalCode}}<br />
{{:shipper.contactAddress.country.name}}<br />
Tel: {{:shipper.contact.phoneNumber}}{{if organization.faxNumber}}, Fax:
{{:organization.faxNumber}}{{/if}}
</div>
</div>
<div class="order-info info-box">
<div class="info-box-title">Freight Quote</div>
<table>
<tr>
<td><strong>Quote Number:</strong></td>
<td>{{:orderNumber}}</td>
</tr>
<tr>
<td><strong>Ref Number:</strong></td>
<td>{{:trackingNumber}}</td>
</tr>
<tr>
<td><strong>Quote Date:</strong></td>
<td>{{:orderDate}}</td>
</tr>
<tr>
<td><strong>Mode of Transportation:</strong></td>
<td>{{:customValues.modeOfTransportationName}}</td>
</tr>
</table>
</div>
Data Binding Basics
jsrender uses {{: }}
for basic data binding. For example:
<p>Customer Name: {{:customerName}}</p>
Handling Null References
jsrender automatically handles null or undefined values by not rendering anything. However, for nested properties, you should use the && operator:
{{if billToContact && billToContact.name}}
<strong>{{:billToContact.name}}</strong><br />
{{/if}}
Conditional Rendering
Use {{if}}
for conditional rendering:
{{if organization.faxNumber}} , Fax: {{:organization.faxNumber}} {{/if}}
Looping and Iterating
Use {{for}}
to iterate over arrays:
{{for charges}}
<tr>
<td>{{:description}}</td>
<td>{{:quantity}}</td>
<td>{{:price}}</td>
</tr>
{{/for}}
Formatting Numbers
Use :n to format numbers, where n is the number of decimal places:
<td>{{price:2}}</td>
This will display the price with 2 decimal places.
Displaying Dates
jsrender doesn't have built-in date formatting. Dates will be displayed in their default format. If you need specific formatting, you should pre-format the date in your data before passing it to the template.
Working with Currencies
For currencies, use number formatting for the amount and display the currency code separately:
<td>{{totalAmount:2}} {{:currency.currencyCode}}</td>
Creating Tables for Data
Here's an example of creating a table for charges:
<div class="section">
<div class="info-box">
<div class="info-box-title">Charges</div>
<table>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Price</th>
<th>Total Amount</th>
<th>Currency</th>
<th>Note</th>
</tr>
{{for charges}}
<tr>
<td>{{:description}}</td>
<td>{{:quantity}}</td>
<td>{{price:2}}</td>
<td>{{totalAmount:2}}</td>
<td>{{:currency.currencyCode}}</td>
<td>{{:note}}</td>
</tr>
{{/for}}
</table>
</div>
</div>
Advanced Techniques
Using Computed Properties
You can use {{: }}
with JavaScript expressions:
<td>{{:price * quantity}}</td>
Creating Custom Tags
For more complex logic, you can create custom tags:
$.views.tags("upperCase", function (value) {
return value.toUpperCase();
});
Then use it in your template:
<td>{{upperCase:description}}</td>
Sample JSON Data
Here's an example of the JSON data structure that could be used with this template:
{
"organization": {
"companyName": "ABC Logistics",
"addressLine": "123 Main St",
"cityName": "Newark",
"stateCode": "NJ",
"postalCode": "07102",
"faxNumber": "+1234567890"
},
"orderNumber": "3915",
"trackingNumber": "TRK123456",
"orderDate": "2024-05-15T10:00:00Z",
"customValues": {
"modeOfTransportationName": "Air"
},
"billToContact": {
"name": "John Doe",
"phoneNumber": "+1234567890",
"billingAddress": {
"formattedAddress": "456 Elm St, Newark, NJ 07102"
}
},
"shipper": {
"contact": {
"name": "ABC Logistics",
"phoneNumber": "+1234567890"
},
"contactAddress": {
"country": {
"name": "United States of America"
}
}
},
"consignee": {
"contact": {
"name": "Jane Smith",
"phoneNumber": "+0987654321"
},
"contactAddress": {
"formattedAddress": "789 Oak St, London, UK"
}
},
"charges": [
{
"description": "Shipping",
"quantity": 1,
"price": 5.8,
"totalAmount": 5.8,
"currency": {
"currencyCode": "USD"
},
"note": "Standard shipping charge"
}
],
"orderCommodities": [
{
"commodity": {
"pieces": 1,
"description": "Widget",
"weight": 0.5,
"weightUnit": "Kg",
"width": 10,
"height": 10,
"length": 10,
"dimensionsUnit": "Cm",
"volumeTotal": 0.001,
"volumeUnit": "Vkg",
"unitaryValueTotal": 1
}
}
]
}
Complete Template Example
Here's a complete example of the freight quote template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Freight Quote</title>
<style>
/* ... (CSS styles from earlier in the guide) ... */
</style>
</head>
<body>
<div class="header">
<div class="company-info">
<h1>{{:organization.companyName}}</h1>
{{:organization.addressLine}}<br />
{{:organization.cityName}}, {{:organization.stateCode}}
{{:organization.postalCode}}<br />
{{:shipper.contactAddress.country.name}}<br />
Tel: {{:shipper.contact.phoneNumber}}{{if organization.faxNumber}}, Fax:
{{:organization.faxNumber}}{{/if}}
</div>
</div>
<div class="order-info info-box">
<div class="info-box-title">Freight Quote</div>
<table>
<tr>
<td><strong>Quote Number:</strong></td>
<td>{{:orderNumber}}</td>
</tr>
<tr>
<td><strong>Ref Number:</strong></td>
<td>{{:trackingNumber}}</td>
</tr>
<tr>
<td><strong>Quote Date:</strong></td>
<td>{{:orderDate}}</td>
</tr>
<tr>
<td><strong>Mode of Transportation:</strong></td>
<td>{{:customValues.modeOfTransportationName}}</td>
</tr>
</table>
</div>
<div class="section" style="display: flex; justify-content: space-between;">
<div class="info-box" style="width: 48%;">
<div class="info-box-title">Bill To Information</div>
<div class="info-box-content">
{{if billToContact && billToContact.name}}<strong
>{{:billToContact.name}}</strong
><br />{{/if}} {{if billToContact && billToContact.billingAddress &&
billToContact.billingAddress.formattedAddress}}
{{:billToContact.billingAddress.formattedAddress}}<br />
{{/if}} {{if billToContact && billToContact.phoneNumber}}Tel:
{{:billToContact.phoneNumber}}{{/if}}
</div>
</div>
<div class="info-box" style="width: 48%;">
<div class="info-box-title">Shipping Information</div>
<div class="info-box-content">
{{if consignee && consignee.contact && consignee.contact.name}}<strong
>{{:consignee.contact.name}}</strong
><br />{{/if}} {{if consignee && consignee.contactAddress &&
consignee.contactAddress.formattedAddress}}
{{:consignee.contactAddress.formattedAddress}}<br />
{{/if}} {{if consignee && consignee.contact &&
consignee.contact.phoneNumber}}Tel:
{{:consignee.contact.phoneNumber}}{{/if}}
</div>
</div>
</div>
<div class="section">
<div class="info-box">
<div class="info-box-title">Quote Charges</div>
<table>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Price</th>
<th>Total Amount</th>
<th>Currency</th>
<th>Note</th>
</tr>
{{for charges}}
<tr>
<td>{{:description}}</td>
<td>{{:quantity}}</td>
<td>{{price:2}}</td>
<td>{{totalAmount:2}}</td>
<td>{{:currency.currencyCode}}</td>
<td>{{:note}}</td>
</tr>
{{/for}}
</table>
</div>
</div>
<div class="section">
<div class="info-box">
<div class="info-box-title">Quote Commodities</div>
<table>
<tr>
<th>Pieces</th>
<th>Description</th>
<th>Weight</th>
<th>Dimensions</th>
<th>Volume</th>
<th>Value</th>
</tr>
{{for orderCommodities}}
<tr>
<td>{{:commodity.pieces}}</td>
<td>{{:commodity.description}}</td>
<td>
{{commodity.weight:2}} {{:commodity.weightUnit[Previous content
remains unchanged]
</td>
<td>{{commodity.weight:2}} {{:commodity.weightUnit}}</td>
<td>
{{commodity.width:2}}x{{commodity.height:2}}x{{commodity.length:2}}
{{:commodity.dimensionsUnit}}
</td>
<td>{{commodity.volumeTotal:3}} {{:commodity.volumeUnit}}</td>
<td>{{commodity.unitaryValueTotal:2}}</td>
</tr>
{{/for}}
</table>
</div>
</div>
<div class="terms-and-conditions">
<h3>Terms and Conditions</h3>
<p>
This quote is valid for 30 days from the date of issue. All rates are
subject to change without notice due to factors beyond our control.
Insurance is not included unless explicitly stated. Delivery times are
estimates and not guaranteed. Payment is due as per agreed terms; late
payments may incur additional charges. Claims for loss or damage must be
filed within 7 days of delivery. The shipper is responsible for ensuring
the shipment does not contain prohibited or restricted items. Charges
may be based on dimensional or actual weight, whichever is greater. Any
duties, taxes, or other charges imposed by customs or other authorities
are the customer's responsibility. This agreement shall be governed by
the laws of [Your Jurisdiction]. By accepting this quote, you agree to
these terms and conditions. {{:organization.companyName}} reserves the
right to refuse service to anyone at its discretion.
</p>
</div>
<div class="signature">Signature: __________________________________</div>
</body>
</html>
Best Practices and Tips
-
Use Meaningful Class Names: Choose class names that reflect the structure and purpose of your document elements. This makes your template easier to understand and maintain.
-
Handle Null References: Always check for the existence of nested properties to avoid errors. Use the
&&
operator for chained property access. -
Use Conditional Rendering: Utilize
{{if}}
statements to conditionally display content based on data availability or specific conditions. -
Leverage Built-in Formatting: Use jsrender's built-in formatting options, like
{{value:2}}
for number formatting, wherever possible. -
Create Reusable Structures: For repeated elements like info boxes or tables, consider creating reusable template structures.
-
Comment Your Code: Add comments to explain complex logic or data handling in your template.
-
Optimize Performance: Minimize the use of complex logic within the template itself. If possible, preprocess data before passing it to the template.
-
Use Custom Tags for Complex Logic: If you find yourself repeating complex logic, consider creating custom tags to encapsulate that logic.
-
Keep Styling Separate: While inline styles can be useful for quick adjustments, try to keep most of your styling in a separate CSS section for better maintainability.
-
Use Flexbox or Grid for Layout: These CSS features can help create responsive layouts that adapt to different screen sizes.
-
Validate Your HTML: Ensure your final HTML is valid and follows best practices for web standards.
-
Optimize for Printing: If your document is likely to be printed, consider adding print-specific styles to ensure it looks good on paper.