easy-template-x-data-binding v0.2.0
easy-template-x-data-binding
Extends the easy-template-x to implement data binding controls via custom XML.
Easy Template X Extensions
Easy Template X is an excellent library for creating word documents from templates.
It handles the processing of the documents contents but does not allow editing of the document's metadata, held in Custom XML files inside the document.
Easy Template X supports extensions which can be run on the documents either before or after it modifies the contents.
Node Example
import * as fs from "fs";
import { TemplateHandler, TemplateHandlerOptions } from "easy-template-x";
// 1. read template file
const templateFile = fs.readFileSync("test/fixtures/files/data binding.docx");
// 2. process the template
const data = {
"/data/CHECKBOX": {
_type: "boolean",
value: true
},
"/data/DATE": {
_type: "date",
value: new Date("2019-04-01T12:00:00Z")
},
"/data/NUMBER": {
_type: "text",
value: "999"
},
"/data/RICH_TEXT": {
_type: "text",
value: `Example Rich Text
Empty line above`
},
"/data/TEXT": {
_type: "text",
value: `Example Text`
}
};
const handler = new TemplateHandler(
new TemplateHandlerOptions({
extensions: {
afterCompilation: [
new DataBindingExtension(createDefaultDataBindingPlugins())
]
}
})
);
const doc = await handler.process(templateFile, data);
// 3. save output
fs.writeFileSync("out/data binding - output.docx", doc);
Input:
Output:
Browser Example
The following example produces the same output while running in the browser. Notice that the actual template processing (step 2) is exactly the same as in the previous Node example.
import { TemplateHandler } from "easy-template-x";
// 1. read template file
// (in this example we're loading the template by performing
// an AJAX call using the fetch API, another common way to
// get your hand on a Blob is to use an HTML File Input)
const response = await fetch("http://somewhere.com/myTemplate.docx");
const templateFile = await response.blob();
// 2. process the template
const data = {
"/data/CHECKBOX": {
_type: "boolean",
value: true
},
"/data/DATE": {
_type: "date",
value: new Date("2019-04-01T12:00:00Z")
},
"/data/NUMBER": {
_type: "text",
value: "999"
},
"/data/RICH_TEXT": {
_type: "text",
value: `Example Rich Text
Empty line above`
},
"/data/TEXT": {
_type: "text",
value: `Example Text`
}
};
const handler = new TemplateHandler(
new TemplateHandlerOptions({
extensions: {
afterCompilation: [
new DataBindingExtension(createDefaultDataBindingPlugins())
]
}
})
);
const doc = await handler.process(templateFile, data);
// 3. save output
saveFile("myTemplate - output.docx", doc);
function saveFile(filename, blob) {
// see: https://stackoverflow.com/questions/19327749/javascript-blob-filename-without-link
// get downloadable url from the blob
const blobUrl = URL.createObjectURL(blob);
// create temp link element
let link = document.createElement("a");
link.download = filename;
link.href = blobUrl;
// use the link to invoke a download
document.body.appendChild(link);
link.click();
// remove the link
setTimeout(() => {
link.remove();
window.URL.revokeObjectURL(blobUrl);
link = null;
}, 0);
}
Live Demo
Checkout this live demo on CodeSandbox 😎
OOXML Data structure
The data is stored in the /CustomXml/itemX.xml in the OOXML document.
Each piece of bound data can be uniquely identified by the XML path from its root.
Use the XML path to the XML tag used to store the data as its identifier.
Currently namespaces and duplicate tag names are not supported.
{
"rootnode/firstnode": {
_type: type
value: value
},
"rootnode/nextnode": {
_type: type
value: value
},
"rootnode/lastnode": {
_type: type
value: value
}
}
For an example of how to format the data see test\integration\templateHandler.tests.ts
The _type dictates which plugin will be used.
The plugin dictates what type the value will have.
Standard plugins
Although internally in the custom XML files all values are stored as text, and the text plugin can be used for all data types, to assist in validating data different plugins are available.
Please feel free to implement plugins for other data types.
Text plugin
Can be used with all content controls. Updates the text of the node with its contents. Expects value to be a string.
Boolean plugin
Mainly used with check box controls. Updates the text of the node with 'true' or 'false'. Expects value to be a boolean.
Date plugin
Mainly used with date box controls. Updates the text of the node with the date in 'yyyy-mm-dd' format. Expects value to be a Date.