{{Mustache}} Helper for Domino and XPages
Previously we had a look, how to use Mustache with the CKEditor to have an editing environment for templates. I glossed over the part where to store and how to use these templates. Let me continue there.
I'll store the template in Notes documents and use an application managed bean to transform a document (and later other things) using these templates.
I have 2 use cases in mind: one is to allow the configuration of HTML notification messages in applications and the other to configure the display of workflow details (more on Workflow in a later post). The approach has two parts:
I also opted to load all templates into memory at once, but only compile them when actually needed. If you plan to have lots of them, you want to look for a different solution.
The class that does the work is the
With this done transforming a document becomes a one liner in SSJS:
There are some interesting details: Mustache has the capability to use partials (think subforms) using the syntax
The
You will notice that the first time the transformation runs, there's a delay before the page displays. That's the step when all templates are loaded and the managed bean gets initialized.
Also have a look at the
Some documents might need special attention, e.g. when groups of field (multi-value or sequential named) form a table of values. You can provide your own resolver for them.
For now the templates are managed in the Notes client interface. Adding a template edit UI is left to your pleasure.
You can generate anything that can be expressed as ASCII stream: Plain Text, HTML, XML, JSON, XSL:FO, ODF, DOCX (the later two need to be zipped before delivery), PostScript, SVG etc. Get the code on GitHub
As usual YMMV. Next stop: transforming other stuff like views and adding more examples.
I'll store the template in Notes documents and use an application managed bean to transform a document (and later other things) using these templates.
I have 2 use cases in mind: one is to allow the configuration of HTML notification messages in applications and the other to configure the display of workflow details (more on Workflow in a later post). The approach has two parts:
- loading (or reloading) the existing templates
- using the templates
I also opted to load all templates into memory at once, but only compile them when actually needed. If you plan to have lots of them, you want to look for a different solution.
The class that does the work is the
MustacheHelper.java
. To make it easy to use, I wrap it into a managed bean and a small SSJS Helper function:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
<managed-bean>
<managed-bean-name>Mustache</managed-bean-name>
<managed-bean-class>com.notessensei.mustache.MustacheHelper</managed-bean-class>
<!-- In a production system that should be application -->
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<!--AUTOGEN-START-BUILDER: Automatically generated by IBM Domino Designer. Do not modify.-->
<!--AUTOGEN-END-BUILDER: End of automatically generated section-->
</faces-config>
function applyTemplate(doc, templateName) {
try {
// Check for init
if (!Mustache.isInitialized()) {
var templateView:NotesView = database.getView("templates");
Mustache.initFromView(session, templateView);
templateView.recycle();
}
return Mustache.renderDocumentToString(templateName,doc);
} catch (e) {
return e.message;
}
}
With this done transforming a document becomes a one liner in SSJS:
return applyTemplate(document1.getDocument(),"Color");
. To demo how it works, I created a sample database.In that database I use 2 computed fields to demo the transfomation of a document into plain text and HTML. You might ask: so what? Keep in mind, that this is only to demo the technique. Real use cases would be notification eMails or cnfigurable summaries from documents where you don't know the fields while you design the solution.
There are some interesting details: Mustache has the capability to use partials (think subforms) using the syntax
{{> common/header}}
. By default Mustache would try to read a file from a file system for that partial. Since we don't have the partials in the file system, we need to provide our own resolver to the Mustache factory:
factory = new DefaultMustacheFactory(new MustacheNotesResolver(templateStrings));
The
templateStrings
are a Map containing the uncompiled Mustache templates. The Resolver code is quite lean:
public class MustacheNotesResolver implements MustacheResolver {
private final Map<String, String> templates;
public MustacheNotesResolver(Map<String, String> templateCollection) {
this.templates = templateCollection;
}
@Override
public Reader getReader(String resourceName) {
if (!this.templates.containsKey(resourceName)) {
return null;
}
return new StringReader(this.templates.get(resourceName));
}
}
You will notice that the first time the transformation runs, there's a delay before the page displays. That's the step when all templates are loaded and the managed bean gets initialized.
Also have a look at the
DocumentResolver
that turns a document into something that Mustache can process.
public class DefaultDocumentResolver implements DocumentResolver {
@Override
public Map<String, Object> resolve(Document doc) {
Map<String, Object> result = new HashMap<String, Object>();
try {
for (Object o : doc.getItems()) {
Item i = (Item) o;
if (i.getValues().size() > 1) {
Collection<String> c = new Vector<String>();
for (Object val : i.getValues()) {
c.add(val.toString());
}
result.put(i.getName(), c);
} else {
result.put(i.getName(), i.getText());
}
Utils.shred(i);
}
} catch (NotesException e) {
e.printStackTrace();
}
return result;
}
}
Some documents might need special attention, e.g. when groups of field (multi-value or sequential named) form a table of values. You can provide your own resolver for them.
For now the templates are managed in the Notes client interface. Adding a template edit UI is left to your pleasure.
You can generate anything that can be expressed as ASCII stream: Plain Text, HTML, XML, JSON, XSL:FO, ODF, DOCX (the later two need to be zipped before delivery), PostScript, SVG etc. Get the code on GitHub
As usual YMMV. Next stop: transforming other stuff like views and adding more examples.
Posted by Stephan H Wissel on 16 November 2014 | Comments (0) | categories: XPages