Variable from include file

Things I have tried

Hello,
I try to include a file with templater code into another templater file with:

<% tp.file.include("[[_templ_incl_File]]") -%>

in this file templ_incl_File I try to declare some variables and do an If-funktion:

<%*
let varYear = await tp.system.suggester(["📆 today", "2023", "2022", "2021"], ["1", "2023", "2022", "2021"], false, "Year..."); 

if (varYear == "1") {
  let varDateAll = tp.date.now("YYYY-MM-DD");
	} else {
  let varMonth = await tp.system.suggester(["Jan", "Feb", "Marz", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"], false, "Month...");

  let varDay = await tp.system.prompt("The day...?");
  varDateAll = varYear + "-" + varMonth + "-" + varDay;
}
 let vartime = await tp.system.prompt("Which time...?"); 
-*>

But in the file, I include this file (code above), there seems to get trouble with the variables
I get the error:

Template parsing error, aborting. 
 varDateAll is not defined
log_error @ plugin:templater-obsidian:61

How do I have to declare the variables so, that it runs round?

You declare the varDateAll inside one branch of the if-then-else, then it’s not known in the other branch.

It’ll be slightly better if you declare it next to varYear, but they’re still declared in the outer scope. You’d be better off using Templater’s user function, and return the new values you want in the outer scope.

1 Like

Thank you for your reply,

I changed it like this:

message:

Templater Error: Template parsing error, aborting. 
 varDateAll is not defined

the other option you mentioned → javascript user functions :flushed:
hard tobaco

You’re almost all the way to a user function, so good for you. What’s a little important to understand now is that your first error message was in the included file, but the last one is in the file you included from.

In that file, there is no definition of the varDateAll, as it’s not in the same scope. To “transfer” values between scopes, you need to use functions and return values, and this is where the user functions of Templater enters the scene. So bare with me for the setup part, and I think you’ll get the gist of it rather soon.

Setup for user functions in Templater

You need to have a folder for the javascript files, which will become your user functions. Make a dedicated folder for your scripts within the vault, and call it whatever you like, i.e. Scripts. After creating it, enter this folder name into Settings > Templater > Script files folder location (close to the end).

Now you need to use an external editor to create a javascript file in this folder, and it makes it a whole lot easier if you keep the name the same for all of this. So say you want the getDateAll function, you’ll create the file getDateAll.js, and for starters it’ll hold this text:

function getDateAll(tp) {
... to be filled out ...
}

module.exports = getDateAll

This pattern you’ll repeat for every function you create, where you’ll change the name of the function, and the tp parameters of your function (or just leave it out, all together). I’ve included the tp, as it makes the next step just a little bit easier.

Build your function

The next step is to code your function, and in your case it’s almost a pure copy-paste from the included file, so now your function should look something like:

async function getDateAll() {
  let varYear = await tp.system.suggester(["📆 today", "2023", "2022", "2021"], ["1", "2023", "2022", "2021"], false, "Year..."); 
  let varDateAll = ""; 
  if (varYear == "1") {
    varDateAll = tp.date.now("YYYY-MM-DD");
  } else {
    let varMonth = await tp.system.suggester(
               ["Jan", "Feb", "Marz", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 
               ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"], 
               false, "Month...");

    let varDay = await tp.system.prompt("The day...?");
    varDateAll = varYear + "-" + varMonth + "-" + varDay;
  }
  // let vartime = await tp.system.prompt("Which time...?"); 

  return varDateAll
  // return [varDateAll, vartime]
}

module.exports = getDateAll

The only thing I’ve done to your code, is (temporarily) remove the start of getting the time. And I’ve commented out a potentially new return variant, when/if you re-add the time part. You’ll then comment out the other return, as the function does exit on the return statement.

Update 2022-12-30: Since the function uses await, the entire function needs to be declared as async, and calls to the function should use await when calling.

Using your script

The new way you’ll call your script now depends on whether you’ll want to use the value for something else, or if you just want to present it out into your markdown file. This will replace your original tp.file.include().

<% tp.user.getDateAll(tp) %>
<%* const varDateAll = await tp.user.getDateAll(tp)
     ... do something more with the varDateAll ...
%>

Finally, if you re-add the time, and don’t include it into the same variable, but use my suggested return, you could get both values using this syntax:

<%*  const [varDateAll, varTime] = await tp.user.getDateAll(tp) 
  ... do something with those variables ...
%>

Update 2022-12-30: Due to our function now being async, it’s needed to call it with await to ensure it completes it’s statements within.

You’re of course free to name the script folder and javascript files as you like. But you need to keep the filename the same as the function name, and the same as the end of the module.exports. And the filename must end in .js, as in getDateAll.js. (Hence, the need to use an external editor (or to install some plugins to allow you to edit/create javascript files from within Obsidian))

Hope this helps, and you understand the ‘hard tobacco’ of Templater’s user functions.

2 Likes

Hello holroy,

What a great explanation, thank you so much, that helps me a whole piece further.
I already thought that it was related to the declaration or that the variable is not to be found in the corresponding file, but why - my knowledge is not sufficient for that… but one is anxious to learn (as well as possible :wink:).

and now to work…

Thank you and all the best for you and your Fellow colleagues for the new year.
you all do a great job here :raising_hand_man:
till next time :wink:

1 Like

well, templater didn’t make it that easy for me…
first he grumbled
no async function... and then
tp is not defined...
so i had a look here:

and put the async in front of function and set the tp in brackets

async function getDateAll(tp) { ...

and it works fine.

with the implement of
// return [varDateAll, vartime]
I’ll take care of that later…

once again thanks, see you soon

Sorry, I was a little unprecise there, but you found the way! :smiley:

1 Like

Not everything has to be served scalding hot… A little effort is all right…
ok…this time it was just bearable :wink: :joy:

1 Like

Well, if I only work with

return varDateAll

and call it in the file with:

<% tp.user.getDateAll(tp) %>

all works fine.
as soon I set in the

let vartime = await tp.system.prompt("Which time...?");
return [varDateAll, vartime]

and call it with:

const [varDateAll, vartime] = tp.user.getDateAll(tp);

the error occurs

Templater Error: Template parsing error, aborting. 
 object is not iterable (cannot read property Symbol(Symbol.iterator))

I hope its only a declaration thing and nothing worst…

It’s most likely linked to the async thingy, which can be a pain in the … !

It seems like <% tp.user.getDateAll() %> automatically does it, whilst you need to manually add the await when calling it. So try the following, since the function needed to be declared as async (due to the await’s inside it):

<%*
  const [varDateAll, vartime] = await tp.user.getDateAll(tp);
  tR += varDateAll + " " + vartime
%>

(As you might have understood, I didn’t fully try out the suggested code. My bad… Sorry, for the confusion. But when you need to use await inside a function, the function needs to be async, and you then need to do await on the function on the outside, as well. )

2 Likes

Hello holroy,

My bad… Sorry, for the confusion

I don’t blame you at all for this in any way.
You sacrifice your free time to enlighten people like me. That can’t be appreciated enough.
So, don’t feel like I’m blaming you in any way for something not working out here.

and now to the topic :wink:

…works fine!

thanks again and all the best!

1 Like

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