Templater - New note with autocompletion of existing frontmatter

Hi everyone, I would like to share some Obsidian Templater code on how you can create a new note/file based on existing frontmatter template file and then autocomplete (modify) properties of the frontmatter in the newly created note.

The whole idea here is to keep separate your Templater code from the frontmatter template file otherwise you have to include the frontmatter with some trick so that Obsidian treats frontmatter information as regular text instead of recognizing frontmatter properties.

For the Templater newcomer, I have been there myself and spent a lot of time, there is also the problem of how you trigger the Tempater code so that it creates your new note/file based on it (i.e. Templater: Create new note from template command, or Alt+N or click the <% templater symbol at the ribbon).

In that case you must not use tp.file.create_new in your code because that will create an extra Untitled file inside the folder which you do not want. Instead I use tp.file.rename to change the Untitled filename of the new file and then tp.file.include to include my frontmatter type inside the new file.

Finally in order to modify the frontmatter, e.g. autocomplete properties or add new properties, you have to use tp.hooks.on_all_templates_executed. This way the file will be created with the specific frontmatter and then it will be modified.

Attention: If you try to trigger the Templater code when your cursor is at the current opened file, your new file/note is created on the same folder with the current note, it is opened and it becomes the new current note.

An alternative is to right-click on the folder you want to create your note/file and run the Templater: Create new note from template command. But again it is opened in the same tab with the previous current note and it becomes the new current note.

There is also a quicker way to create the new note/file by adding a new Folder Template in Templater configuration.

Advantage of using this method

You can add content after your Templater code and include javascript variables and frontmatter properties. For example I have added a Meta-Bind plugin INPUT box.

My frontmatter type (Note.type)

---
tags:
  - type/note
title: 
description: 
url: 
publish: false
---

My templater code

<%*
const ext = ".note"
const typefilename = "Note.type"

// Rename NEW Untitled file
const filename = tp.date.now("YYYYMMDD")+moment().format('HHmmss')+ext
await tp.file.rename(filename);

// Include frontmatter properties from the <.type> file
const type = await tp.file.find_tfile(typefilename);
tR += await tp.file.include(type);

// Modify frontmatter by adding created_at and updated_at properties
tp.hooks.on_all_templates_executed(async () => {
	// construct timestamp
	const dfrmt = "YYYY-MM-DD" ;
	const tfrmt = "HH:mm:ss" ;
	const zfrmt = "+03:00" ;
	var timestamp = tp.date.now(dfrmt)+"T"+moment().format(tfrmt)+zfrmt ;
	
	const file = tp.file.find_tfile(filename);		
	await app.fileManager.processFrontMatter(file, (frontmatter) => {
		frontmatter["created_at"] = timestamp;
	    frontmatter["updated_at"] = timestamp;
	});
});
%>
`INPUT[text:description]`

Many thanks to all Obsidian and Templater developers and contributors, stay tuned.

References

Templater: Trigger Templater on new file creation

Trying to get a Templatr template to move new files to a folder based on front matter

1 Like

Create New note and open it in a new tab

There is an alternative for the code above, but pay attention because it is triggered differently and works differently

<%*
const folder = "Notes"
const ext = ".note"
const typefilename = "Note.type"

// construct timestamp
const dfrmt = "YYYY-MM-DD" ;
const tfrmt = "HH:mm:ss" ;
const zfrmt = "+03:00" ;
var timestamp = tp.date.now(dfrmt)+"T"+moment().format(tfrmt)+zfrmt ;

// Create NEW file at the specified folder and 
// include frontmatter properties from the <.type> file
const filename = tp.date.now("YYYYMMDD")+moment().format('HHmmss') + ext
const type = await tp.file.find_tfile(typefilename);
await tp.file.create_new(type, filename, false, folder);

// Modify frontmatter by adding created_at and updated_at properties
const file = await tp.file.find_tfile(filename);		
await app.fileManager.processFrontMatter(file, (frontmatter) => {
	frontmatter["created_at"] = timestamp;
	frontmatter["updated_at"] = timestamp;
});

// Open the new file in a new tab
await app.workspace.getLeaf("tab").openFile(file);
%>

The only similarity with the previous code in my main post is that you have the same (Note.type) file for your frontmatter properties. But there are many significant differences here from the Templater code in this reply:

  • This Templater code can be triggered from any current note that is opened from any folder.
  • You must not right-click on the specified folder (e.g. Notes) to create your new note/file. Instead you run Templater: Open Insert Template modal command and select your template with the Templater code.
  • The paradox here is that this Templater code will not insert anything at the opened/current file but it will create a new file.
  • You do not need to use tp.hooks.on_all_templates_executed to modify the frontmatter
  • The new file will be opened in a new tab and it will become the current file.
  • You must not add any content for the note after the Templater code, instead you can modify the “Note.type” file. Be careful for any white space before or after the code or use Templater whitespace control.
  • You must not add a new Folder Template in Templater instead if you want a quicker way to trigger this templater code you can add a Template hotkey

Perhaps someone can also make a youtube video to highlight the differences between these two specific use cases so that Templater newcomers can understand better this functionality. It took me a long time to understand how this works despite the fact that I watched videos and read Templater documentation and related posts

References

2 Likes