You can configure docxtemplater with an options object by using the constructor with two arguments.
const options = { paragraphLoop: true, linebreaks: true };
const doc = new Docxtemplater(zip, options);
doc.render(/* data */);
The name of this option is parser
(function).
With a custom parser, you will be able to redefine how the tags resolve to some data.
For example, if your template is :
And your data is
{
"name": "John"
}
The parser will provide you a way to customize how to resolve the data for each tag.
The default parser is the following :
const doc = new Docxtemplater(zip, {
parser(tag, meta) {
/*
* In our example above :
* - tag is "name" because {name} contains the "name" string.
* - if the template was `Hello { foo + bar }`,
* the value of the tag variable would
* be : " foo + bar "
*/
console.log(meta.tag); // { type: "placeholder", value: " foo + bar "}
return {
get(scope, context) {
/*
* In our example above, scope is `{ "name": "John" }`
* because that is the data passed to docxtemplater
*/
console.log(context); // the context : { num, meta, scopeList, ...}
if (tag === ".") {
return scope;
}
// return the property "name" of the scope object.
return scope[tag];
},
};
},
});
doc.render(/* data */);
With a custom parser you can parse the tags to for example add operators like '+', '-', or even create a Domain Specific Language to specify your tag values.
To enable those features, you need to edit your parser function.
The most common parser that I recommend is to use the angular parser.
You can also read the following advanced tutorial if you want to write your own parser from scratch.
In your template, you normally write :
If you want to change the characters used for starting and ending tags, you can set up your custom delimiters:
new Docxtemplater(zip, {
delimiters: { start: "[[", end: "]]" },
});
// Default delimiters are { delimiters: { start: '{', end: '}' } }
Then, you will be able to use :
The paragraphLoop option has been added in version 3.2.0. Since it breaks backwards-compatibility, it is turned off by default.
It is recommended to turn that option on, since it makes the rendering a little bit easier to reason about.
new Docxtemplater(zip, { paragraphLoop: true });
With the paragraphLoop enabled, the following rule is applied :
If the opening loop {#users}
and the closing loop {/users}
are both on separate paragraphs, and there is no other content on those paragraphs, treat the loop as a paragraph loop (ie create one new paragraph for each loop). Docxtemplater will then remove the first and last paragraphs (the ones containing the loop open and loop close tags).
It allows to loop around paragraphs without having additional spacing.
When you write the following template
Most users of the library would expect to have no spaces between the different names.
The output without the option is as follows:
With the paragraphLoop option turned on, the output becomes:
The paragraphLoop feature works only with paragraphs, not with line breaks.
See this tip in the FAQ to understand how to view and replace linebreaks.
If the paragraph contains leading or trailing whitespace, for example:
{#users}
foo
bar
{/}
In this example, the {#users} tag has two whitespaces before the tag.
A helpful feature in Word is the "show invisible characters" option, documented here: Show Hidden Characters in Word. This allows you to show those invalid characters.
If there are multiple loops on the same line:
It should instead be written as :
If you use line breaks instead of paragraph breaks:
Paragraph Break: Used to skip a line and start a new paragraph on the second line below existing text. Press "Enter" to insert a Paragraph Break.
Line Break: Used to start a new line of text immediately below existing text. Press "Enter" while holding the "Shift" key to insert a Line Break.
If the closing loop is not on a separate paragraph.
The following will not be considered a paragraph loop
Each start and end loop must be in a separate paragraph, like this :
You can customize the value that is shown whenever the parser (documented above) returns null
or undefined
. The default value is the following:
function nullGetter(part, scopeManager) {
if (!part.module) {
return "undefined";
}
if (part.module === "rawxml") {
return "";
}
return "";
}
const doc = new Docxtemplater(zip, { nullGetter });
doc.render(/* data */);
This means that the default value for simple tags is to show "undefined". The default for rawTags ({@rawTag}) is to drop the paragraph completely (you could enter any xml here).
The scopeManager variable contains some meta information about the tag, for example, if the template is: {#users}{name}{/users}
and the tag {name}
is undefined, scopeManager.scopePath
will be equal to ["users", "name"]
By default, if you use the following data :
doc.render({
description: "My description\nMultiline\nMultiline",
});
And following template :
The linebreaks (\n
characters) will be ignored, all characters will be written on the same line.
If you set the linebreaks
option to true, if your data contains newlines (\n
), those will be shown as newlines in the document.
Use it like this :
const doc = new Docxtemplater(zip, { linebreaks: true });
doc.render({
description: "My description\nMultiline\nMultiline",
});
By default, if your template is this :
Hello {foo
This will trigger an error.
It is possible to completely ignore those errors by using the following :
const doc = new Docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
syntax: {
allowUnopenedTag: true,
allowUnclosedTag: true,
},
});
doc.render(/* data */);
Those options are available since docxtemplater 3.52.0 (for allowUnclosedTag
) and 3.40.0 (for allowUnclosedTag
).