My workaround for the date placeholder conflict (Templater, Periodic Notes)

I believe this has not been reported before, at least I couldn’t find anything on this forum. After some experimenting, I finally found a solution to my particular problem, and I thought that maybe someone might be interested. Also, I found some posts (eg., here, or here) also looking for a solution to a similar problem, at least if I understood the authors correctly.

TL;DR

I found a way to “unify” the {{date}} and tp.date.now placeholders. See below for the solution.

The setup

  • In my vault, I store all my daily journal entries, which I create and navigate using the Periodic Notes and Calendar plugins.
  • I also use the Templater plugin instead of the regular Templates Core plugin, because I make use of the Folder Templates feature (the vault also stores other, irregular notes in different folders).
  • Finally, I use the Homepage plugin to show a welcome page at startup, which contains a link to today’s journal entry (using dataviewjs).

There are two ways for me to create today’s journal entry, if not already existing:

  1. via the Periodic Notes plugin (this includes opening today’s entry from the Calendar plugin’s widget in the right sidebar).
    In this case, the Periodic Notes plugin inserts the current date everywhere the template contains a {{date}} placeholder, which does also work as expected if I create, say, yesterday’s entry using this method; or
  2. by clicking the link on the welcome page.
    In this case, the note will be created in the exact same location and with the exact same filename format that are also set in the Periodic Notes settings. The Templater plugin, especially it’s Folder Templates feature, ensures that the correct template is used, inserting today’s date everywhere the template contains something like <% tp.date.now() %>.

The problem

In principle, I would need 2 seperate templates, as there are 2 different date placeholders {{date}} and tp.date.now, used by the Periodic Notes or Templater plugin, respectively, depending on how today’s note is created; but I dislike the idea of having to manage 2 templates that are supposed to do the exact same thing, especially since the template contains large blocks of dataviewjs code that I happen to modify quite frequently.

The solution

The solution I came up with:

<%* 
const date_from_pnp = "{{date:YYYY-MM-DD}}";
let datestring;
if (date_from_pnp === "{" + "{date:YYYY-MM-DD}}") {
	datestring = tp.date.now("YYYY-MM-DD");
} else {
	datestring = date_from_pnp;
}
-%><% datestring %>

If this is triggered via Periodic Notes (and I suppose, also the Daily Notes plugin, but have not tested), the first {{date}} placeholder will be replaced with the date corresponding to the created note, before Templater is triggered. Therefore, date_from_pnp holds the actual date string, not the placeholder, which is then compared to the not expanded placeholder (the second placeholder is “masked”, ie. cannot be expanded by Periodic Notes, by constructing it from substrings). In case the comparison is true, the note has in fact been created without Periodic Notes, and we use the Templater tp.date.now to insert the current date, assuming the note was created by clicking the link on the welcome page. Otherwise, if the comparison is false, the first {{date}} placeholder must have been expanded before being assigned to date_from_pnp, and we can use Templater to just insert the contents of date_from_pnp.

I am aware that this could possibly be solved/worked around in other ways, eg., by extracting the date from the note title, or via templates “calling” other templates. However, I find this solution quite elegant and hope that it might help someone at some point.

:beers:

2 Likes

Nice solution!

You can shorten the code as follows and avoid the let declaration:

<%*
const date_from_pnp = "{{date:YYYY-MM-DD}}"
const datestring = date_from_pnp === ("{" + "{date:YYYY-MM-DD}}") ? tp.date.now("YYYY-MM-DD") : date_from_pnp
-%><% datestring %>

Thanks for the suggestion!

Although I would always prefer a longer but more “folded” chunk of code over a one-liner from hell, your suggestion does indeed look more elegant. It is only a few days ago that I wrote my very first line of javascript.

Given the occasion, what’s the preferred practice of accepting answers in this category? Since I didn’t really ask a question…

1 Like

You’re welcome, and hats off, for your first steps with JavaScript!

You should be able to mark the answer as the “solution” if you accept it as such. I have not initiated a discussion myself, but I have seen it.