Dataview: reuse DQL queries?

This is nice. How do I get this to work with DataviewJS?

Hi @ThurMeijer! If you mean how to use my workaround above with DataviewJS, then I suggest you don’t! :smiley:

Instead, use Dataview’s existing dv.view() mechanism, which is designed for JS script reuse.

I was thinking about the execute / load suggestion @orand mentioned, because I really like the option to be able to see it as a md-file.
Is that also possible with the dv.view-option?

No, I don’t think you can execute md files with dv.view() – it’s very particular on what it will load.

And I think dv.execute() is specific to DQL queries, so I don’t think it will work for JavaScript.

That’s about the extent of my knowledge. Good luck!

You should be able to just replace execute with executeJs

dv.executeJs(await dv.io.load("Scripts/reusable-query.md"))

reusable-query.md should contain raw JavaScript that’s not wrapped in a code block.

2 Likes

Hi,

I’m the new guy around here, and I’ve got some tips and questions related to this topic. Which might be off target completely, but here goes.

First of all, using the Plaintext plugin, and adding js as an extension, one is able to edit javascript within Obsidian, albeit without some of the bells and whistles of a more dedicated code editor, like Visual Code 2. Only downfall so far, is that to create the file initially you either need to create an ordinary note within Obsidian, and rename it from .md to .js outside of Obsidian. Or you’ll create the file outside of Obsidian.

Secondly, I found a view such files with syntax highlighter, see my own answer in my own thread: Raw embed of javascript into a code block? - #3 by holroy :smiley:

Lastly, is there a particular reason you’re using dv.execute() instead of dv.query()? The latter seems to have an option to pass a file, pretending to be this, so that it can mimic being on the original note even more than what dv.execute() seems to do. It would also allow for even more post-processing, and handling after query execution if one would want that. See Dataview: Function to get length of unique values OR using nested queries - #2 by holroy, for an example where I post process a DQL query to show summary of the summaries.

Hi @holroy !

Welcome! Thanks for your note and your ideas. Your use of the plaintext, button, and templater plugins is very clever!

Yep. it’s because I want to embed the query results directly on the page. I don’t need to do any post-processing on the results.

1 Like

wow this is super cool. This trick can also be used to re-use a JavaScript file like below:

dv.executeJs(await dv.io.load("Scripts/dailyTaskDistribution/dailyTaskDistribution.js"))
1 Like

Wonderful work here. I stumbled across this completely accidentally today and it solved a problem I knew that I had before I began looking for a solution.

I’m developing a template that shows movies watched, books read each month. Across many years, there are many files I need to create. The problem with normal templating is should I make a change, I need to update many files.

This solves that perfectly, One .js file linked to all the others.

2 Likes

This is so useful. Thanks, @Craig.

  1. If I want multiple queries, is it best to put them in one js file or separate js files?

2. Does anyone know how to use this with the DQL query in a callout?

Two minutes after asking that question, the solution came to mind: put the DVJS in a callout in the placeholder. Doh!

> [!INFO] Quote  
> ```dataviewjs
>dv.view("/_inbox/t1");
>```

Hi @anon63144152, great question. I’m generally a fan of more atomic notes, so I would probably keep it to one file per query and then refer to them individually.

Of course, if the two queries depend on each other, or would always be together, then it might make sense to keep them in the same file.

1 Like

I think I am going to have to go for one query in each JS file as I can’t get two queries in the same file to run. I would ideally like to add some inline JS snippets in the JS file as well but not been able to make those work either. Baby steps. Lots of reading to do.

But brilliant idea. Loving the paths it is taking my mind along. :heart_eyes_cat::exploding_head::person_in_lotus_position:t3:

Inline JS snippets don’t work correctly in live preview from memory, have a look in reading mode - you might find they’re working there.

1 Like

Something like this works when placed directly in a MD note in both live preview and reading mode:

`$= moment(dv.current().file.day.toISODate()).diff(moment('2022-11-14'), 'years').toLocaleString('en-en') + " years"` / `$= moment(dv.current().file.day.toISODate()).diff(moment('2022-11-14'), 'days').toLocaleString('en-en') + " days"`   

But if I put it in its own JS file—exactly as it is written above—and then call it in a MD note it doesn’t work:

> [!INFO] Quote  
> ```dataviewjs
>dv.view("/js/t1");
>```

I am also trying to put two DQL tables in one JS file but can’t get that to work as yet.

dv.execute(`

TABLE
file.tags as Tags
WHERE file.cday = this.file.day
or file.mday = this.file.day
SORT file.mtime desc
LIMIT 10

`);

dv.execute(`

dataview
TABLE
file.tags as Tags
FROM #obsidian
SORT file.mtime desc
LIMIT 10

`);

Busy reading the effing manual :smiling_face_with_tear:

The following example is given on the Dataview help pages:

If I create a JS file (called t1) with:

dv.execute("LIST FROM #obsidian");
dv.execute("TABLE title, author FROM #css");

…only the second query is executed when t1 is embedded in a MD file:

```dataviewjs
dv.view("/_inbox/t1");
```

Shouldn’t both execute in line with the help pages example?

Thanks for any suggestions.

1 Like

Tried a couple of different solutions but always get some (varying) error messages.

I have the following dataview query:

TABLE WITHOUT ID Schlagwort, map(rows, (r) ="* " + link(r.file.link, r.title) + "<br>" + " (" + r.kategorie + ")") AS Einträge
FROM !"bibliothek"
WHERE file.path !=this.file.path
FLATTEN file.tags as Schlagwort
GROUP BY Schlagwort
WHERE econtains(this.file.etags, Schlagwort)

It works absolutely fine when put directly into a note. When put into a separate note and called (in the active note) via

$= dv.execute(await dv.io.load("path/to/file.md"))

(as @orand suggested here), it says “No implementation of ‘map’ found for arguments: array, boolean”.

What am I doing wrong?

This part needs to become

map(rows,  (r) => "* "

for starters. Don’t know if there are other errors, as well.

2 Likes

That’s it - you’re my hero! :partying_face:

Essentially that code is:

`$= moment(....) + " text " ` / `$= moment( ... ) + "text"`

Which will not execute within javascript either, or more correct it’ll not produce any sensible output. Remember that inline dataviewjs query is kind of surrounded by dv.span() in order to produce its output.

So if you change the file to include to something like:

dv.span(moment( ...) + "text " + moment( ... ) + "text")

It’ll happily execute it.

Regarding the double DQL queries to be executed, that’s another matter it seems. There is an extra dataview before the second query, which makes it not compile, and give an error message on the console. But even with that fixed, it’s a little tricky to get it to work properly.

There are concurrency issues related to what runs when, and also related to how the dv.execute (or dv.query which I also tested) and the other dv.functions() calls are executed and hook into the DOM. At least, when I added the javascript above, two dv.header() calls, and the two dv.execute() the order got messed up, and only one of the two queries (seemingly random which one) was executed.

My full javascript-file
dv.span(
  moment(dv.current().file.day.toISODate())
    .diff(moment('2022-11-14'), 'years')
    .toLocaleString('en-en') + 
  " years / " +
  moment(dv.current().file.day.toISODate())
    .diff(moment('2022-11-14'), 'days')
    .toLocaleString('en-en')
  + " days" )
                 
dv.header(2, "First query")

dv.execute(`
  TABLE
    file.tags as Tags1
  WHERE file.tags 
  WHERE file.cday = this.file.day
     OR file.mday = this.file.day
  SORT file.mtime desc
  LIMIT 10
`); /* */

dv.header(2, "Second query")

dv.execute(`
  TABLE 
    file.tags as Tags2 , file.cday
  WHERE file.tags
  SORT file.mtime desc 
  LIMIT 10
`);          

So I’m thinking it’s not wise to include too much of this stuff, especially in the context of calling through dv.view(). I’ve never experience this order issue, or stuff being left out when doing it directly within dataviewjs.

Apologies for the tardy reply—not been online for a few days. :scream:

Thanks for the help. Realize that this is beyond what I can work with at the moment. Either need to learn more or to just keep things simple.

Right now the fun of Obsidian is bleeding away over the frustration of things I can’t tame. Time to take a break. :stop_sign: :wave:t4: :crying_cat_face:

1 Like