Eko's answer is correct. I would like to expand on this answer and do two things:
- Use the tree recorder to update the template
- use jsdom to find the location in the template to update
With jsdom and similar tools, serializing an Angular template either will not work -- or break any camelCase, [boxed], (parenthetical), #tagged -- attributes. So we will only use jsdom to find the location of where we want to update.
function updateTemplate() {
return (tree: Tree) => {
const buffer = tree.read(TEMPLATE_PATH);
const content = buffer?.toString();
if (!content) {
throw new SchematicsException(`Template ${TEMPLATE_PATH} not found`);
}
// the includeLocations flag is very important here
const dom = new JSDOM(content, { includeNodeLocations: true });
const element = dom.window.document.querySelector('ul');
const locations = dom.nodeLocation(element);
if (!locations) {
throw new SchematicsException(`<ul> could not be found in ${TEMPLATE_PATH}`);
}
// now we update the template using the tree recorder
// we don't use jsdom to directly update the template
const recorder = tree.beginUpdate(TEMPLATE_PATH);
const listItem = ` <li><a href="/contact">contact</a></li>\n`
recorder.insertLeft(locations.endTag.startOffset, listItem);
tree.commitUpdate(recorder);
return tree;
};
}
Again, eko's answer is correct. This answer illustrates how to use jsdom and the tree recorder together to update an Angular template -- which is useful for inserting directives, events, tags and methods into elements, wrapping sections and more complex transformations.