You are currently offline, serving cached version

Types of tags

The syntax of docxtemplater tags is inspired by the language agnostic Mustache specification.

Normal tags start with an alphabetical character, and other types of tags start with special prefixes, for example :

  • {#loop} and {/loop} to start and close a tag for the data part "loop"
  • {@input} to insert raw XML data
  • when using the image-module {%src_url} will add an image for the "src_url" data part.

Introduction

With this template (input.docx):

Hello {name} !

And given the following data (data.json):

{
    name: "John";
}

docxtemplater will produce (output.docx):

Hello John !

Conditions

Conditions start with a pound and end with a slash. That is {#hasKitty} starts a condition and {/hasKitty} ends it.

{#hasKitty}Cat’s name: {kitty}{/hasKitty}
{#hasDog}Dog’s name: {dog}{/hasDog}

and this data:

{
    "hasKitty": true,
    "kitty": "Minie"
    "hasDog": false,
    "dog": null
}

renders the following:

Cat’s name: Minie

For a more detailled explanation about Conditions, have a look at Sections

You can also have "else" blocks with Inverted Sections

Loops

In docxtemplater, conditions and loops use the same syntax called Sections

The following template:

{#products}
{name}, {price} €
{/products}

Given the following data:

{
    "products": [
        { name: "Windows", price: 100 },
        { name: "Mac OSX", price: 200 },
        { name: "Ubuntu", price: 0 }
    ]
}

will render :

Windows, 100 €
Mac OSX, 200 €
Ubuntu, 0€

To loop over an array containing primitive data (eg string):

{
   "products": [
       "Windows",
       "Mac OSX",
       "Ubuntu"
   ]
}
{#products} {.} {/products}

Will result in:

Windows Mac OSX Ubuntu

Sections

A section begins with a pound and ends with a slash. That is {#person} begins a "person" section while {/person} ends it.

The section behaves in the following way:

Type of the valuethe section is shownscope
falsy or empty arrayneverNA
non empty arrayfor each element of arrayelement of array
objectoncethe object
other truthy valueonceunchanged

This table shows for each type of value, what is the condition for the section to be changed and what is the scope of that section.

If the value is of type boolean, the section is shown once if the value is true, and the scope of the section is unchanged.

If we have the section

{#hasProduct}
{price} €
{/hasProduct}

Given the following data:

{
    "hasProduct": true,
    "price": 10
}

Since hasProduct is a boolean, the section is shown once if hasProduct is true. Since the scope is unchanged, the subsection {price} € will render as [10 €]

Creating multiple table rows

It is possible to create multiple rows in a table

NameAgePhone Number
{#users}{name}{age}{phone}{/}
{
    users: [
        { name: "John", age: 22, phone: "+33653454343" },
        { name: "Mary", age: 25, phone: "+33666666666" },
    ],
}

Will render the following :

NameAgePhone Number
John22+33653454343
Mary25+33666666666

Inverted Sections

An inverted section begins with a caret (hat) and ends with a slash. That is {^person} begins a "person" inverted section while {/person} ends it.

While sections can be used to render text one or more times based on the value of the key, inverted sections may render text once based on the inverse value of the key. That is, they will be rendered if the key doesn't exist, is false, or is an empty list. The scope of an inverted section is unchanged.

Template:

{#repo}
Repo name : {name}
{/repo}
{^repo}
No repos :(
{/repo}

Data:

{
  "repo": []
}

Output:

No repos :(

Sections and newlines

New lines are kept inside sections, so the template:

{#repo}
{name}>
{/repo}
{^repo}
No repos :(
{/repo}

Data:

{
  "repo": [
      {name: "John"},
      {name: "Jane"},
  ]
}

Will actually render

NL
John
NL
NL
Jane
NL

(where NL represents an emptyline)

The easiest to make this work is to enable the paragraphLoop option, like this :

// Now, all sections in the form of :
// {#section}
// something
// {/section}
// will keep just the inner paragraphs, and drop the newlines of the outer section
const doc = new Docxtemplater(zip, { paragraphLoop: true });

An other less recommended way if you don't want to set this option, is to remove the new lines after the start of the section and before the end of the section.

For our example , that would be:

{#repo} {name}
{/repo} {^repo} No repos :( {/repo}

Raw XML

It is possible to insert raw (unescaped) XML, for example to render a complex table, an equation, …

With the rawXML syntax the whole current paragraph (w:p) is replaced by the XML passed in the value.

{@rawXml}

with this data:

doc.render({
    rawXml: `
    <w:p>
        <w:pPr>
            <w:rPr>
                <w:color w:val="FF0000"/>
            </w:rPr>
        </w:pPr>
        <w:r>
            <w:rPr>
                <w:color w:val="FF0000"/>
            </w:rPr>
            <w:t>
                My custom
            </w:t>
        </w:r>
        <w:r>
            <w:rPr>
                <w:color w:val="00FF00"/>
            </w:rPr>
            <w:t>
                XML
            </w:t>
        </w:r>
    </w:p>
    `,
});

This will loop over the first parent <w:p> tag

If you want to insert HTML styled input, you can also use the docxtemplater html module

Lambdas

const doc = new Docxtemplater(zip);
doc.render({
    userGreeting: (scope) => {
        return "How is it going, " + scope.user + " ?";
    },
    users: [
        {
            name: "John",
        },
        {
            name: "Mary",
        },
    ],
});

with the following template :

{#users}{userGreeting}{/}

will render :

How is it going, John ?
How is it going, Mary ?

It will call the function userGreeting twice (one for the user "John", and for the user "Mary"), with the current scope as first argument, and the scopeManager as the second argument.

Set Delimiter

Set Delimiter tags start and end with an equal sign and change the tag delimiters from { and } to custom strings.

Consider the following contrived example:

* {default_tags}
{=<% %>=}
* <% erb_style_tags %>
<%={ }=%>
* { default_tags_again }

Here we have a list with three items. The first item uses the default tag style, the second uses erb style as defined by the Set Delimiter tag, and the third returns to the default style after yet another Set Delimiter declaration.

Custom delimiters may not contain whitespace or the equals sign.

It is also possible to change the delimiters globally by using docxtemplater options object.

Dash syntax

When using sections, docxtemplater will try to find on what element to loop over by itself:

If between the two tags {#tag}______{/tag}

  • there is a table cell tag (<w:tc> or <a:tc>) , that means that your loop is inside a table, and it will expand the loop over the table row (<w:tr> or <a:tr>).
  • in other cases it will not expand the loop

With the Dash syntax you can specify the tag you want to loop on: For example, if you want to loop on paragraphs (w:p), so that each item in the loop creates a new paragraph, you can write:

{-w:p loop} {inner} {/loop}
Talk with sales Contact us