Templater JS: Extra blank "Untitled" note created when triggering new template creation

I’ve been running tests with Templater js code to make a Meeting Note template that inherits YAML properties from another note (through Dataview’s API). I finally have everything working right, except that every time I trigger the template creation, an extra “Untitled” note is created.

Obsidian also automatically opens the “Untitled” file after note creation instead of the actual new Meeting Note.

My Code

What’s cool about this js template is the YAML inheritance from the Project Overview file. I’m not an experienced coder, so I created the script by modifying code from these useful posts:

Inherit or pass on Metadata Values from Active File when creating New File

Get Dataview inline field from different file using Templater

Here is the template:

<%*
// Prompt to select Project Overview file
// Applies filter to suggest relevant files
const pOverview = (
  await tp.system.suggester(
    (item) => item.basename,
    app.vault.getMarkdownFiles().filter((file) => file.name.includes("§"))
  )
).basename;

// Access Project Overview frontmatter with DataviewAPI
const pMeta = DataviewAPI.page(tp.file.find_tfile(pOverview).path);

// Generate the new file name in the desired format
const currentDate = new Date();
const formattedDate = currentDate.toISOString().slice(0, 10);
const newFileName = `❉ ${formattedDate} ${pMeta.Project} Meeting Note`;

// Prompt the user for Meeting Attendees
const attendees = await tp.system.prompt("Meeting Attendees (comma-separated)");

// Define the content for the new note with inherited metadata
const content = `---
class: Meeting Note
Project: ${pMeta.Project}
Artist: ${pMeta.Artist}
Date: ${formattedDate}
---
up:: [[${pOverview}]]

# ${newFileName}

Attendees:: ${attendees}

### Summary



## Notes



## Reflection



`;

const baseFolder = app.vault.getAbstractFileByPath(pMeta.file.folder)

await tp.file.create_new(content, `${newFileName}.md`, true, baseFolder);
_%>

Example:

Say I want to create a new meeting note for Project X

I already have a note “§ X - Overview” (“§” is used to denote a project file and to keep that file at the start of alphabetical lists)

YAML for the note “§ X - Overview” would contain -
Project: X
Artist: Y

1/ I open Command Palette and type/select “Templater: Create new note from template”

2/ I select the template file that contains the js code for my Project Meeting Note template

3/ I am then prompted (by tp.system.suggester) to select one of my Project Overview notes. The properties of this file will be used in to populate the meeting note template.

4/ I select “§ X - Overview”

5/ I am then prompted for “Meeting Attendees”, which I can type in.

6/ The new meeting note is populated with metadata inherited from “§ X - Overview”. The new note is automatically renamed with my chosen naming convention (“❉ YYYY-MM-DD X Meeting Note”) and moved into the same folder as “§ X - Overview”.

7/ For some reason, a new note “Untitled” has been created, placed in my default new note location (/Captures), and opened in my tab.

– The “Untitled” note seems to be created in between steps 2 and 3

Questions

Any idea why this extra “Untitled” note is being created?
None of my other templates use js, but they work without creating an extra unnecessary note. Am I missing something basic about Templater?

Let’s walk through the flow.

  1. You run the “Templater: Create new note from template” command. At this point, there will be a file created called “Untitled.md” in your default new file location. The “Templater: Create new note from template” command will always create a new file for you.
  2. Your template code executes in your “Untitled.md” note. Part of your template code includes creating another file that is named based on some of your template code.

If you are not expecting two notes to be created, then you should either use a different Templater command that does not create a file for you, or you should not create a file as part of your template code, and just have content in your template note.

Here’s an example of still using the same Templater command, putting the content in the note the Templater command creates instead of in a new note:

<%*
// Prompt to select Project Overview file
// Applies filter to suggest relevant files
const pOverview = (
  await tp.system.suggester(
    (item) => item.basename,
    app.vault.getMarkdownFiles().filter((file) => file.name.includes("§"))
  )
).basename;

// Access Project Overview frontmatter with DataviewAPI
const pMeta = DataviewAPI.page(tp.file.find_tfile(pOverview).path);

// Generate the new file name in the desired format
const currentDate = new Date();
const formattedDate = currentDate.toISOString().slice(0, 10);
const newFileName = `❉ ${formattedDate} ${pMeta.Project} Meeting Note`;

// Prompt the user for Meeting Attendees
const attendees = await tp.system.prompt("Meeting Attendees (comma-separated)");

// MOVE THE FILE
await tp.file.move(`${pMeta.file.folder}/${newFileName}`);

// PUT CONTENT OUTSIDE OF TEMPLATER COMMAND AS PLAIN TEXT, WITH <% %> TO PUT VARIABLES IN
_%>
---
class: Meeting Note
Project: <% pMeta.Project %>
Artist: <% pMeta.Artist %>
Date: <% formattedDate %>
---
up:: [[<% pOverview %>]]

# <% newFileName %>

Attendees:: <% attendees %>

### Summary



## Notes



## Reflection



2 Likes

Yep, that was it – I was definitely “missing something basic about templater” ^^

I didn’t understand that the “Untitled” note was my project meeting note, just after executing the tempater command to create a new file with my specified properties.

The solution was as you said:

  • remove “tp.file.create_new”
  • use “tp.file.move”
  • put content outside of templater command as plain text, using <% %> to put variables in

I think the “content” variable was throwing me.

Thank you very much for taking the time to explain this.

For anyone wondering, here’s my updated “Project Meeting Note Template”:

<%*
// SELECT PROJECT OVERVIEW FILE
const pOverview = (
  await tp.system.suggester(
    (item) => item.basename,
    app.vault.getMarkdownFiles().filter((file) => file.name.includes("§"))
  )
).basename;

// ACCESS PROJECT OVERVIEW FRONTMATTER WITH DATAVIEW API
const pMeta = DataviewAPI.page(tp.file.find_tfile(pOverview).path);

// GENERATE THE NEW FILE NAME IN THE DESIRED FORMAT
const currentDate = new Date();
const timeZone = 'America/New_York';
const options = { timeZone: timeZone, year: 'numeric', month: '2-digit', day: '2-digit' };
const correctedDate = new Intl.DateTimeFormat('en-US', options).format(currentDate);
const dateComponents = correctedDate.split('/');
const formattedDate = `${dateComponents[2]}-${dateComponents[0]}-${dateComponents[1]}`;
const newFileName = `❉ ${formattedDate} ${pMeta.Project} Meeting Note`;

const newFileTitle = `${formattedDate} ${pMeta.Project} Meeting Note`;

// PROMPT USER FOR "MEETING ATTENDEES"
const attendees = await tp.system.prompt("Meeting Attendees (comma-separated)");

// MOVE THE FILE
await tp.file.move(`${pMeta.file.folder}/${newFileName}`);
_%>
---
class: Meeting Note
Project: <% pMeta.Project %>
Artist: <% pMeta.Artist %>
Date: <% formattedDate %>
---
up:: [[<% pOverview %>]]

# <% newFileTitle %>

Attendees:: <% attendees %>

### Summary



## Notes



## Reflection

Pretty much exactly as @Zachatoo had it.

I made some minor tweaks to even better fit my use-case:

  • added time-zone specification to fix an issue with the date being wrong when creating note too close to next day
  • added new variable newFileTitle which removes my “❉” meeting note identifier from H1

I’m sure this is not the best looking code, considering my inexperience, but maybe it will help someone else.

1 Like

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