Rendering Programmatically Defined Templates Asyncronously
Describe the Bug:
This is a documentaion bug! When using a programatically defined template the docs state: "The third argument to loadTemplate is a boolean describing whether the template is async or not. By default, Eta will assume that the template is synchronous."
Using this advice, calling a programatically defined template using renderAsync will result in an EtaNameResolution error. (includeAsync has the same issue)
To Reproduce:
const eta = new Eta();
const test = `test`;
eta.loadTemplate('@test', test, true); // As advised
const res = await eta.renderAsync('@test');
EtaNameResolutionError [EtaNameResolution Error]: Failed to get template '@test'
Expected Behaviour:
The template should be found and rendered.
Package & Environment Details
- Environment: Node: 21.5.0
- Version: 3.4.0
Additional Context:
Removal of the Async call will succeed:
const eta = new Eta();
const test = `test`;
eta.loadTemplate('@test', test, true); // Boolean variable is doing nothing
const res = eta.render('@test');
console.log(res);
As will passing the object that the code actually expects:
const eta = new Eta();
const test = `test`;
eta.loadTemplate('@test', test, { async: true});
const res = await eta.renderAsync('@test');
console.log(res);
Just a slighly more complete example to assist future travellers who are loading their templates from a database (or wherever!) while the documentation / examples for Eta are still rather sparse:
const eta = new Eta({
tags: ['<?', '?>'], // I find <% awkward to type (long live PHP!)
varName: 'data', // Not a fan of `it` either
debug: true,
cache: true,
});
const layoutTest = `
<!DOCTYPE html>
<html>
<head>
<title><?= data.title ?></title>
</head>
<body>
<?~ await includeAsync('@headerTest', data) ?>
<?~ data.body ?>
<?~ await includeAsync('@footerTest', data) ?>
</body>
</html>
`;
const headerTest = `
<header>
Header: <?= data.title ?>
</header>
`;
const footerTest = `
<footer>
Footer: <?= data.title ?>
</footer>
`;
const mainTest = `
<? layout('@layoutTest', data) ?>
<main>
<h1>Main: <?= data.title ?></h1>
</main>
`;
eta.loadTemplate('@layoutTest', layoutTest, { async: true });
eta.loadTemplate('@headerTest', headerTest, { async: true });
eta.loadTemplate('@footerTest', footerTest, { async: true });
eta.loadTemplate('@mainTest', mainTest, { async: true });
const res = await eta.renderAsync('@mainTest', { title: 'Test title' });
@paul-norman thanks for catching that! I just pushed a quick clarification to the docs, but I'd be open to a PR with more details / a better explanation!
I've just started actually porting some EJS code to ETA today, so I'm a total beginner with the system. However, after I've used it for a little while I will take another look at the docs and see what doesn't make sense to me then...