open-xml-templating/docxtemplater

Tag Confliction Between Angular Parser Index and Chart Module

micahvandeusen opened this issue · 4 comments

Environment

  • Version of docxtemplater : 3.34.3
  • Used docxtemplater-modules : ChartModule
  • Runner : Browser

How to reproduce my problem :

Use the {$index} in a template as described at https://docxtemplater.com/docs/angular-parse/#retrieving-index-as-part-of-an-expression and #397 while having the chart module loaded.

The stack trace returned is:

error TypeError: Cannot read properties of undefined (reading 'subchartManager')
    at chart-module.min.js?1678389364:2:256403
    at Array.forEach (<anonymous>)
    at t.value [as postparse] (chart-module.min.js?1678389364:2:256364)
    at docxtemplater.js:3477:24
    at Array.reduce (<anonymous>)
    at _postparse (docxtemplater.js:3476:22)
    at postparse (docxtemplater.js:3479:20)
    at docxtemplater.js:2422:30
    at Array.reduce (<anonymous>)
    at Object.postparse (docxtemplater.js:2406:32)

It appears that the default for the prefix of the chart module conflicts with angular parser. There is this documentation but it doesn't list out what prefix would need to be changed for the chart module: https://docxtemplater.com/docs/faq/#changing-the-end-user-syntax

Hello @micahvandeusen ,

You can always do the following :

const ChartModule = require("docxtemplater-chart-module");
const content = fs.readFileSync("demo_template.docx");
const data = {
	chart1: {
		categories: ["5th Qtr", "6th Qtr", "7th Qtr", "8th Qtr"],
		data: [130, 20, 40, 10],
		title: "xxx",
	},
};

const chartModule = new ChartModule();
chartModule.prefix = "$$";
const zip = new PizZip(content);
const doc = new Docxtemplater(zip, { modules: [chartModule] });
doc.render(data);

This way, all charts should now begin with "$$" instead of just "$".

Another option is to add a specific case for the name "$index", and catch this case so that it won't be handled by the chart module.

You can do it like this :

const indexCatchModule = {
    name: "Catch $index module",
    requiredAPIVersion: "3.0.0",
    parse(placeHolderContent) {
        if (placeHolderContent === "$index") {
            const type = "placeholder";
            return {
                type,
                value: placeHolderContent
            };
        }
    },
};
const doc = new Docxtemplater(zip, { modules: [indexCatchModule, chartModule] });

Note that the indexCatchModule should be put before the chartModule because the module order is the order in which the modules can "handle" the placeHolderContent.

@edi9999 thank you for the quick resolution. The indexCatchModule didn't appear to solve it but changing the chart prefix worked.

Here is the indexCatchModule that should work :

const indexCatchModule = {
    name: "Catch $index module",
    requiredAPIVersion: "3.0.0",
    matchers() {
        return [
            [
                "$index",
                "",
                {
                    priority: 1000,
                    value: "$index",
                }
            ],
        ];
    },
};
const doc = new Docxtemplater(zip, { modules: [indexCatchModule, chartModule] });