TIP: E4X for HTML Templates

I was working on a client project and saw they were doing a lot of string concatenation for building some HTML. I converted it to E4X, but i noticed there weren’t many examples on the forum, so I thought I’d share a few very simple ones.

	var someVar = 1
	var someVar2 = 2
	var template = <html>
						<body>
							<table border="0">
								<tr>
									<td>{someVar}</td>
									<td>{someVar2}</td>
								</tr>
							</table>
						</body>
					</html>
	var merged = template.toString()
	application.output(merged)

The result is:

1 2

You can also do it dynamically in some loops:

	var ds = databaseManager.createEmptyDataSet(0,2)
	ds.addRow(['a','b'])
	ds.addRow(['d','e'])
	ds.addRow(['g','h'])
	
	var template = 	<html>
								<body>
									<table border="0">
									</table>
								</body>
						</html>
	
	
	for(var i=1; i<=ds.getMaxRowIndex(); i++){
		template.body.table.appendChild(<tr>
														<td>{ds.getValue(i,1)}</td>
														<td>{ds.getValue(i,2)}</td>
												</tr>)
	}
	
	var merged = template.toString()
	application.output(merged)

The result is:

a b
d e
g h

Have fun with these. Lots more that you can do with E4X.

Even better yet, use Velocity ;)

With a “template1.html” placed in the reports folder, containing:

<html>
  <body>
	 <table border="0">
		<tr>
		   <td>$someVar</td>
		   <td>$someVar2</td>
		</tr>
	 </table>
  </body>
</html>

call:

var merged = plugins.VelocityReport.renderTemplate('template1.html', {someVar: 1, someVar2: 2});
application.output(merged);

The advantages of using a template file is that you can edit it in any html editor, place it under your preferred versioning system and Velocity will pick up the changes automatically, each time you render (no need to redeploy your solution)…

But if you really prefer to use inline html, you can do:

var template = <html>
                  <body>
                     <table border="0">
                        <tr>
                           <td>$someVar</td>
                           <td>$someVar2</td>
                        </tr>
                     </table>
                  </body>
               </html>;
   var merged = plugins.VelocityReport.evaluateWithContext(template.toString(), {someVar: 1, someVar2: 2});
   application.output(merged);

Either way, you will get:

<html>
1 2
> ```

With template2.html, containing:

<html>
  <body>
	 <table border="0">
		#foreach($row in $ds)
			<tr>
			#foreach($value in $row)
				<td>$value</td>
			#end
			</tr>
		#end
	 </table>
  </body>
</html>

call:

var ds = databaseManager.createEmptyDataSet(0,2);
ds.addRow(['a','b']);
ds.addRow(['d','e']);
ds.addRow(['g','h']);
var merged = plugins.VelocityReport.renderTemplate('template2.html', {ds: ds});
application.output(merged);

you get:

<html>
a b
d e
g h
> ```

The Velocity language is simple (see Velocity - VelocityReport Plugin - ServoyForge, easily readable, and when it comes to String manipulation, Velocity is optimized for speed.

And there’s tons more you can do with it!

Great examples Patrick! Personally I don’t think I would use Velocity just to render HTML. I usually will use what’s built in before relying on a call to an external component, but there are definitely some more complex use cases that would benefit from Velocity.
I hope the main take away from people is that there are better options than string concatenation for HTML!

Indeed, most applications nowadays need to manipulate not just HTML, but also all kinds of structured String-based files and data, and Velocity can render any String structure based on a template, can be HTML, XML, JSON, CSS, JavaScript, basically any text-based format…

Personally, I find “just rendering HTML” to be pretty cumbersome when you integrate it directly inline in your code… it kinda hurts my eyes! :D
I find it less readable than a pure HTML file outside of the application, so even in that case, I think it’s still a good idea to use Velocity, especially when one of the advantages of having externalized templates is to make them easy to update on the fly, without the need to redeploy…
It’s a big plus if you’ve ever needed to update your solution because there was a comma missing in your template!

As to what’s built-in or not, I would say that Velocity is now in version 3.5.74 - it’s been used for many years in production for all sorts of projects and it’s maintained and improved constantly (I use it myself all the time for my client’s projects and have all incentives to keep it up to date).

But you’re right, there are many ways to skin a cat!

Fun fact!

The JSX syntax is similar to the E4X Specification (ECMA-357). E4X is a deprecated specification with deep reaching semantic meaning. JSX partially overlaps with a tiny subset of the E4X syntax. However, JSX has no relation to the E4X specification.

https://facebook.github.io/jsx/#prior-art

Great samples Scott!

After two days trying to solve a problem with HTML content in a form I found your post yesterday and solved it in five minutes. This should be part of the documentation on the wiki.

Regards,