Changes to Frontmatter properties from Templater javascripts are not saved

What I’m trying to do

I’m trying to write Templater scripts that read Frontmatter information and based on that write other Frontmatter data. The use case is that I insert these template scripts in existing files (or add them to a button) and run them to quickly update the Frontmatter information. However, after the scripts run, the updated data is not saved in the current file.

Below is an example. This script grabs a link to another file linked in the Frontmatter field ‘Project’. This linked file has Frontmatter information that includes a ‘Projectnr’ field. The script copies the information and saves this in the Frontmatter of the active file.

When I run this script (e.g. using the command ‘Templater: Replace templates in the active file’), something weird happens…I see the Projectnr is changed to the right value, but almost immediately the value is reversed again. And if after that I hit cmd-z, the new, correct value reappears (and the inserted Templater code block reappears too). How do I fix this?

<%*
// Get TFile of the note where the Template is applied
const currentFile = tp.file.find_tfile(tp.file.path(true));

// Read the frontmatter of the current file to get the project link
const currentFrontMatter = await app.metadataCache.getFileCache(currentFile)?.frontmatter;
const projectLinkMarkdown = currentFrontMatter[‘Project’];

if (projectLinkMarkdown) {
// Extract the filename from the Markdown link format [[filename]]
const projectName = projectLinkMarkdown.slice(2, -2);

// Find the TFile of the linked project
const projectFilePath = app.metadataCache.getFirstLinkpathDest(projectName, currentFile.path);
if (projectFilePath) {
    // Access the frontmatter of the linked file
    const projectFileFrontMatter = await app.metadataCache.getFileCache(projectFilePath)?.frontmatter;
    const projectNumber = projectFileFrontMatter['Projectnr'];

    if (projectNumber) {
        // Update the current file's frontmatter with the project number from the linked file
        await app.fileManager.processFrontMatter(currentFile, (frontmatter) => {
            frontmatter["Projectnr"] = projectNumber;
        });

    } else {
        alert("Project number not found in linked file.");
    }
} else {
    alert("Linked project file not found.");
}

} else {
alert(“No project linked in the frontmatter.”);
}
%>

Things I have tried

I’ve tried adding the following code to force save and refresh, but that didn’t help.

// Save the file explicitly
await app.vault.modify(currentFile, await app.vault.read(currentFile));

// Force a refresh of the current file await
app.workspace.activeLeaf.openFile(currentFile, { eState:app.workspace.activeLeaf.getViewState() });

The problem I encounter is very similar as described in this forum post:

but the solution in here doesn’t help me forward in writing my own scripts that access and modify the Frontmatter data.

1 Like

You’re experiencing a race condition on when it’s Templater turns to edit and when it’s your ProcessFrontMatter() turn to edit the file, often ending up with the latter loosing the battle. There are at least two ways to deal with this, both showcased in other forum threads. That is to either use setTimeout() to trigger the call to ProcessFrontMatter() or to use tp.hooks.on_all_templates_executed(). A typical example is given in the link.

This latter function is a new contender, but I do believe its the better option nowadays since it leaves out some guesswork as to how long you need to wait before it’s safe for setTimeout() to trigger the command.

Bonus tip: How to present code properly in a forum post

If you want to showcase either markdown, or code blocks, or dataview queries properly in a forum post, be sure to add one line before and one life after what you want to present with four backticks, ````. This will ensure that any other backticks (like in code blocks or queries) is properly shown.

Awesome! That worked. Thanks - also for the bonus tip :).

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