eta icon indicating copy to clipboard operation
eta copied to clipboard

Rendering Programmatically Defined Templates Asyncronously

Open paul-norman opened this issue 2 years ago • 2 comments

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 avatar Apr 09 '24 10:04 paul-norman

@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!

bgub avatar Apr 09 '24 16:04 bgub

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...

paul-norman avatar Apr 21 '24 16:04 paul-norman