Templater - How to import js function from one file into other file?

As title says with examples below how to import function Bar in Foo?

I tried just doing an import but it fails with “Cannot use import statement outside a module”
Then I figured I should probably do something like module.import in some way but dunno how.

Example files:

Foo.js

Do import somehow?

function Foo() {
    Bar();
}
module.exports = Foo;

Bar.js

function Bar() {
    console.log("bar");
}
module.exports = Bar;

On a sidenote I tried adding topic tags for js, javascript, code, etc but there were no options for them so they could not be added.

Some of the Templater user scripts examples suggest to pass the tp as an argument, and that allows for automatic imports as well, as then the functions are available through the user scripts.

With that in mind I made the following files:

foo.js

function foo(tp) {
 
  console.log('foo');
  return "foo" + tp.user.bar(tp);
}

module.exports = foo

bar.js

function bar(tp) {
 console.log("bar");
 return "bar"
}

module.exports = bar

Some random test file

<%+ tp.user.foo(tp) %>

Which indeed returned “foobar” as expected, when I’m previewing it. I’m getting some type error thingy, seen in the console, but it does do the expected stuff.

Regards,
Holroy

1 Like

Thanks for a quick reply!

This is an interesting idea and I certainly would not mind doing it like this.

I’m a little uncertain as to whether I should check it as solution or not since it technically did not solve the question of how to import. I think I will let it be for a few days and see if somebody else has more input otherwise I will just mark this answer as solution.

1 Like

I used to pass tp as an argument, but I recently started doing this rather than pass the variable, and I haven’t noticed any negative effects:

const tp = app.plugins.plugins['templater-obsidian'].templater.current_functions_object

If I run a function like tp.file.folder(), it is indeed the correct folder for the currently open note, even though I didn’t pass the tp variable from the script that’s actually executing inside that note.

2 Likes

That would eliminate the need for passing tp around although tp is still needed.

I haven’t see this app object before. That is some nice little extra to know about.

Apart from whatever it is actually intended to be used for I could see it perhaps having some interesting use case combined with dataviewjs for showing some information about plugins or other type of data. Could be put on some dashboard or something.

I will keep that in mind. Thanks for the info.

In that case, you might find it useful to know you can access Dataview the same way.

You can also set up Templater class files, and include all that boilerplate in the constructor:

class main {
  constructor() {
    this.dv = app.plugins.plugins.dataview.api
    this.tp = app.plugins.plugins['templater-obsidian'].templater.current_functions_object
  }

  someFunction() {
    return this.tp.file.title
  }

  async anotherfunction() {
    return 'foo'
  }
}
module.exports = main

Then access them from another Templater file with:

<%*
// Include the class
const yourClass = new tp.user.classFile()
// Execute a function
yourClass.someFunction()
%>
4 Likes

@dev01 as to your actual question in the original post, you can require rather than import in your templates or user scripts:

const yourScript = require(app.vault.adapter.basePath + '/path/to/your/script.js')
4 Likes

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