[Solved] Would using Handlebars offer an improvement for my workflow?

Hi,

At the moment I have a Print Context that has a lot of key, value pairs for my templates. So, for example:

@txt_field@	@val_field@

I have a separate javascript “displayTitleValuePair” that fetches the title (the key field that starts with txt_) with the name “field” from an external JSON file and the linked value (the one that starts with val_) with the replacement value. This javascript is called in each script that I created for each specific key, value pair. So there are around 20-30 of those in my template and this is also the number of scripts on average.

function displayTitleValuePair(pTitle, pTitleVal, pTextVal, pBodySnippet) {

	var resultInfo = pBodySnippet;
	if (!isEmpty(pBodySnippet)) {
			resultInfo.find("@txt_" + pTitle + "@").html(pTitleVal);
			resultInfo.find("@val_" + pTitle + "@").html(pTextVal);
	}

	return resultInfo;
}

As I do not want to have any fixed text in my template whenever possible and only placeholders this works fine. The added benefit is that when I need the value of a specific title (the one that starts with txt_) to change I simple replace the specific text in the json file and all the templates that use this text have it immediately without me going through all the templates and hunt for the specific text.

I have been reading up about Handlebars and I’m not sure if it can help my workflow.
Right now I do not use html snippets for my design templates as each document is different with only little overlap so using that does not make sense for me.
If I could use external handlebar snippets I might be able to add the displayTitleValuePair as a custom Handlebars helper and add that in the snippet I can move the entire design for a template to an external file and make changes to that whenever necessary and I would not have to open the template
to make changes there. I can then also cut down on the number of scripts in my template as they are then replace by references in the handlebar snippet (at least the scripts that do not require additional logic).

Am I right in my assumption that I can do this and will this give me a performance improvement?
As the external content still needs to be loaded from disk for each document generation and then needs to be compiled with the javascript still being executed for each key, value pair it might make things slower but I would like to be sure before I take the time to change everything to match the new
flow.

Could someone shed some light on this?

Hi @dvdmeer,

In 2022.1 you could use Handlebars expressions directly in a section but that wouldn’t really offer any benefits since you would still need to create a script to find and replace those Handlebars expressions. You are encouraged to add Handlebars expressions to HBS snippets instead.

In 2022.2 has improved support for Handlebars. There is a new option (enabled by default for new templates) that automatically processes Handlebars expressions in sections, so there is no real need to use HBS snippets. This would cut down on the time you’d need to refactor your template.

Whether either of these options improves performance is difficult to say, but the potential is definitely there, since find and replace scripts (either using text-based selectors or the “find” function) are notoriously slow.

Hi @Sander,

Handlebar expressions are nice but I am confused about the data source that is used to replace the tags {{ txt_myfield }} {{ val_myfield }} properly. As far as I can see this refers to the datamapper but as I am using a key, value data pair where the value might come from the datamapper but the key is a title that comes from an external json file.
How would I go about handling this as I can only apply 1 data source and I have not read anywhere in the documentation that this can be some other than the datamapper?

If I can find the right method to use Handlebar expressions I can create an external handlebar snippet that holds the entire design template html code with all the handlebar tags included that will be translated properly during compiling.

Hi @Sander,

I have found that I can pass the json data that I loaded into a variable as the data source and instead of using the Handlebars.render I used a separate compile and then calling the function separately for the translation.
This works both for the datamapper information (via the record) and my json data. Unfortunately it only works once. So I can either translate my titles or my values but not both as everything in {{ }} is translated in 1 pass and anything that cannot be found is replaced by an empty string instead.

Is there a way to combine 2 different data sources so I can do the replacement in 1 go?
And I was hoping to do it otherwise in 2 passes but as all {{ }} are replaced I cannot do a second pass.

Hi @dvdmeer,

As you already noticed you can render against any object, not just against the current record. Perhaps we should have documented this more clearly.

Assuming your keys are in a JSON file and your values are fields in the current record, you could do:

const json = loadjson(...);
Handlebars.render(content, { json, record })

… assuming the JSON has a key called “key1” and your record has a field called “field1”, your content could then look like this:

{{json.key1}} {{record.field1}}

Note that { json, record } is a shortcut for { json: json, record: record }.

I’m not entirely sure if this fits your use case though. If there is any custom logic you may have to define a helper.

I tried the render function but it already gives me an error when I combine them like you indicated:

image

And this is the function:
image

It does work when I write it like this:

var handlebar = Handlebars.render( “snippets/Sample.hbs”, { json: gTexts, record: record });

And in the handlebars snippet I have the following:

Thank you for your input. Now I can see if I can convert my template into something interesting with handlebars.

Sorry, I now realize that 2022.2 has an updated script engine that supports the { json, record } shortcut I mentioned. In 2022.1 you would have to write it in full, like you already found out: { json: json, record: record }.

Right now it is only possible to add an regular Handlebars snippet in the resource list instead of also being able to add a remote Handlebars snippet. I know it is possible with the render function to include a complete path + filename but I would like to add a feature request to also include a remote Handlebars script to bring it in line with the rest of the snippet possibilities.

Makes sense and added an Improvement Request to our backlog (internal ref SHARED-87815)