Templater: Iterate through frontmatter list, edit each individual element of array

Hi everyone! Unfortunately I can’t find a solution to this problem, despite searching the forums for days. However, I’m sure the solution can’t be too complicated - But maybe my trials are :smiley: I’m don’t know Javascript too well, which is why I’m struggling with the Syntax.

What I’m trying to do

I’m trying to create a template with templater that grabs exisiting frontmatter list and creates links to notes for each individual element.
Say, we are in a movie note and the frontmatter list contains names of actresses featured in the movie:

title: Batman Returns
year: 1992
starring:
* Michael Keaton
* Danny DeVito
* Michelle Pfeiffer
* Christopher Walken
* Michael Gough
* Pat Hingle
* Michael Murphy

Now, a templater template should grab the “starring” array and link a note to each of the elements, to cross reference the movie note with actors notes:

*Batman Begins* features [[Michael Keaton]], [[Danny DeVito]], [[Michelle Pfeiffer]], [[Christopher Walken]], [[Michael Gough]], [[Pat Hingle]] and [[Michael Murphy]].

Things I have tried

While templater natively allows to reference frontmatter arrays like so:

<% tp.frontmatter.starring %> = Michael Keaton,Danny DeVito,Michelle Pfeiffer,Christopher Walken,Michael Gough,Pat Hingle,Michael Murphy

<% tp.frontmatter.starring[0] %> = Michael Keaton

Executive commands in templater, however, don’t. I’m getting no output with following lines:

<%* tp.frontmatter.starring %> 
<%* tp.frontmatter.starring[0] %> 

Nonetheless they don’t thow an error either. So it seems that the array is detected somehow.

Anyways, my approach would be to iterate through the array in a for loop and put “[[” and “]]” around each entry. As far as I know , for loops in templater are only possible in executive commands. So I tried for days to get access to the frontmatter array. The closest I got is from a solution posted here: Change yaml list with templater

It accesses the frontmatter externally in order to change it. Which in my case is quite an overkill, I think. Also, I really don’t know how to implement a for loop here:

<%* 
await app.fileManager.processFrontMatter(tp.config.target_file, (fm) => { 
const index = fm.starring?.indexOf("Michael Keaton");
const arrLen = fm.starring?.length;

// Changing the metadata
if ( index != undefined ) fm.starring[arrLen - 1] = "Test" ;})

%>

Any ideas for an easy solution here?

All my best!

When you’re using the executive block of Templater, aka <%*, you need to append the output to the tR variable. So the very basic variant would be to do:

<%* tR += tp.frontmatter.starring %>

However, this is a one time addition as when the template is executed it’s “forgotten”, so if you add more actors the list produced by the template above will not be updated.

So if you’re likely to update the starring property, you’d either need to reinsert that template, or use a dataview instead to show the list.

Lastly, within the executive block you can use ordinary javascript for loops, or join() functions to customise the output. But in all cases you need to append the output to the tR variable.

1 Like

Oh, I see! Thanks so much, holroy! That indeed was the missing part I needed.

So, for anyone wondering - A solution to my problem would look something like this:

<%*  
for (let $i = 0; $i < tp.frontmatter.starring.length; $i++) {
	tR += "[[" + tp.frontmatter.starring[$i] + "]] ";
	}

%>

A more fancy way to use it in running text, like I mentioned in my example above would be to include another if statement:

*Batman Begins* features <%*  
for (let $i = 0; $i < tp.frontmatter.starring.length; $i++) {
	tR += "[[" + tp.frontmatter.starring[$i] + "]]";

	if ($i < tp.frontmatter.starring.length - 2) {
		tR += ", ";
	} else if ($i < tp.frontmatter.starring.length - 1){
		tR += " and ";
	}
}

%>

As mentioned by @holroy this is merely for a one-time execution - which for me, is the intended use. When the frontmatter is updated afterwards, the templater script has to be re-run.

Thank you so much for your help!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.