DataviewJS Snippet Showcase

Dataview and Dataview JS for real novices.

I have tried to find a couple of tutorials out there but have found that the gap between a simple dataview query and the same in dataview JS is quite big. If you are new to coding and just want that little bit extra that DataviewJS gives you but are not that good at coding it can be a real challenge. So I thougt I write a little about my setup(really task focused right now) and give a code examples. Maybe it can help someone else to bridge the gap… :slight_smile:

I write all my notes in a daily pages. Its a real mix of meeting notes, tasks and just good to know things.

I am trying out a system that I found at Steve Boyds page here: How I Use Daily Notes In Obsidian [Wonkish] - by Stowe Boyd.
Instead of using hashtags for tags I create some of my own with the following structure [ø:: ”tag”] where ”tag” is the group I want for this task. if it is a task formyself i would write
’- [ ] [ø:: me] ”text of what should be done”.
If i have a task with a due date it would look like this:
’- [ ] [ø:: me] [due:: 2022-05-16] ”text of what should be done by this date”
Both of these of course without the ’ at the beginning to make it a task in obsidian.

I also asign some tasks with the tag ”today”.
So for my daily template I want to list all my tasks wit a due date.
Next I want all my task that should be done today.

I started in Dataview and this worked but dataview wants to group everything with a header and that is to me not a good way to present it.
So below is dataview and dataviewjs querys for listing all tasks with duedates that are not completed, sorted ascending.

Dataview query for listing all tasks with a due date that is not completed. Grouped by due date ascending
TASK
WHERE !completed
WHERE due
GROUP BY due
SORT due asc
DataviewJS query for listing all tasks with a due date that is not completed. Sorted ascending but not grouped by anything.
dv.taskList(dv.pages().file.tasks .where(t => !t.completed).where(t => t.due).sort(t => t.due, "asc"), false)

I have noticed that even though I enjoy the system of designing my own tags with the ø:: system it also makes it a bit more complicated when trying to achieve things that most likely is a lot easier if I would have stuck to the original hashtag system. But I like the way it looks. :slight_smile:
I know this is really simple compared to everything here but I found it quite hard to get the Dataviewjs query to do what I wanted. Hopefully someone might have use of it.

3 Likes

So now to my next challenge and question.

So the first part of my daily template is all task with due dates
After this I do tasks that are not completed and I have marked as today group by ”tag” if I have any.
These tasks looks like this in my files: - [ ] [ø:: idag] ”Any thing I want to fokus on today”
Below is the dataview query I have for this and it works as it should but I dont want the grouping behavior of dataview so I turn to DataviewJS

(idag=today in swedish)

Dataview query for tasks marked as today
TASK
WHERE !completed
WHERE ø = "idag"
GROUP BY ø

However, this dataviewJS is not working. I am pretty sure that that is due to me not quite understanding how I can filter on the ”ø” I use as my tags.

DataviewJS query for tasks marked as today
dv.taskList(dv.pages().file.tasks.where(t => !t.completed).where(t => t.ø(”idag”)), false)

Any suggestions would be helpful. :slight_smile:

Replying to myself here. :slight_smile: I really do not get it.

The below code gives me all my task

dv.taskList(dv.pages().file.tasks .where(t=> !t.completed) .where(t=>t.ø), false)

But when I try to filter out only my today(idag) tasks it wont work.

dv.taskList(dv.pages().file.tasks .where(t=> !t.completed) .where(t=>t.ø.includes(”idag”)), false)

What am I doing wrong?

How to skip non-existing notes when querying?

Hi, I just post my question at the Dataview plugin snippet showcase thread. However, after a few attempts, I think DataviewJS might be the way to go. Can anyone provide any tips for a snippet for this? Thanks!

Anyone knows how to skip non-exist note in the FROM statement?

I want to review my bad habit in my weekly note, yet I wasn’t writing journal everyday. As a result, I always get a prompt complaining about dataview could not resolve link during link lookup.

I used to create the notes I missed manually but it gets more and more annoying as my vault is full of empty journal notes now. So, I am wondering if there is a good way to skip the note that doesn’t exist?

Here is the query I wrote.

list
FROM  
	outgoing([[2022-05-16]])
	or outgoing([[2022-05-17]])
	or outgoing([[2022-05-18]])
	or outgoing([[2022-05-19]])
	or outgoing([[2022-05-20]])
	or outgoing([[2022-05-21]])
	or outgoing([[2022-05-22]])
	and #Habit 

Ok, I found a solution. I am not sure however if this is the way it should be done but it works.

dv.taskList(dv.pages().file.tasks
	.where(t => !t.completed)
	.where(t => t.text.includes("ø:: idag")), false)

This gives me all my tasks that I have with the ”tag” today(idag).
It would be nice to know if this is the way I should work with this ”ø:: ” format that I am using(and like) or if there is a better way.

1 Like

Hello Luis,

sorry for my super late answer. Forgot to turn on the forum notifications…

in case you still need help here, I put together this dataviewjs code that at least worked with my dummy data:

```dataviewjs
const flattened = [];
dv.pages()
	.where(b => b.term)
	.map(p => {
		p.term = dv.array(p.term)
		p.definition = dv.array(p.definition)
	
		for (let i = 0; i < p.term.length; i++) {
			flattened.push({term: p.term[i], definition: p.definition[i]})
		}
	});
	
dv.table(['Term','definition'], flattened
		 .sort(a => a.term,'asc')
		 .map(a => [a.term,a.definition]))
```

This code takes all terms and definitions and put them into a flattened map, which you then use to render the table. Mind that this means two things: (a) you lose all other information from the page and cannot “just” append more info to the table without also touching the map function. (b) This only works if you always have the same amount of “terms” and “definition” keys.

7 Likes

Hi this is so helpful and currently trying to set it up. I have copied over your text and I have used a file that contains the stipulated “birthday” frontmatter, but for some reason my table is just completely empty? It is rendering correctnyl but has no entries in? So I am thinking that there must be something wrong with my annotation on the target note? Could you perhaps explain how I should be formatting my notes so that they are included on this?

I am also a little confused about the “searchterm” aspect on the birthday tracker note, is there something I need to do on the target note to make it recognised as a “People” note?

Many thanks for your extremely detailed post!

Try changing your searchterm: '"People'" to searchterm: "#Friends" so that the tracker targets all notes with the tag ‘#Friends’. Right now, it is searching for notes including the word ‘People’ which doesn’t seem to exist in the birthday note you have.

This has worked! Thank you so much for your help.

#help

[Please let me know if more info is required]

I need a little assistance in writing an inline JS query to give me the number of orphan notes in my vault. I have a home page that gives me stats like inbox items, in-process items and so on. Attaching a reference image.

Orphan Notes JS Help

I have a reasonable knowledge on Dataview and have used the (inlinks) and (outlinks) concept to fetch as a table. But I need a number (the number of orphan notes) and nothing else, thus the inline dataviewjs requirement.

NOTE: dviqjs: is a custom prefix I have assigned for Dataview-inline-JS

I got into studying Norse mythology and history last year, which resulted in a ton of pages for various people, terms, what have you. I also imported a lot of Norse text and translations into Obsidian. It got a bit wide and crazy at times. Especially since a lot of info wasn’t sourced from the original text, but references to references.

So I wrote this footer to add to my notes, which makes sure that any links to the page from original (or translated) text gets highlighted if I haven’t already referenced it on the page. That way the original source material gets the spotlight rather than just relying on general backlinks, and whenever I see an “unlinked attestation”, I’ll click in on the note and see exactly what the source material said, which helps me fill out my knowledge about the topic.

Each page has the following at the end:

```dataviewjs
dv.view("00 Meta/Javascript/query_attestations")
```

And query_attestations contains:

let pg = dv.current();

if (dv.pages("#📖").where(b => b.file.outlinks.includes(pg.file.link)).where(b => !pg.file.outlinks.includes(b.file.link)).length > 0) {
    dv.header(2, "Unlinked attestations");
    dv.list(dv.pages("#📖")
        .where(b => b.file.outlinks.includes(pg.file.link))
        .where(b => !pg.file.outlinks.includes(b.file.link))
        .file.link
    );
}
4 Likes

I found out today a way to quickly see the values returned by DataviewJs. I don’t know if it has been shared here. But just in case it might help someone.
If you open the DevTools (CTRL+SHIFT+I) you have access to all DataviewJs’s commands. They are found by typing DataviewAPI in the DevTool’s Console. This way you can quickly see what’s right or wrong in your query.

Here’s an example:
image

14 Likes

I was searching high and low for two days for any way to audit all my YAML keys/fields in my vault and couldn’t find anything, so I went ahead and coded it myself. My implementation is simple, but I’ll probably use it as a launching point for other projects (and I’m hoping somebody else finds it useful, too!).

I keep one note with this query for reference so I can spot-check whether I have any keys or fields misspelled, capitalized differently, etc., since I hate to think something might get lost from my queries due to a typo. It’s both a blessing and a curse that you can put whatever you want in there!

I believe that, as long as you have the same versions of Obsidian (v0.14.15) and the Obsidian Dataview plugin (v0.5.36) installed that I do, you should literally be able to copy/paste this into a DataviewJS codeblock and it should just work for you…?

// Unique YAML Keys Audit
// Brought to you by Jocelyn Tuohy
// 2022.06.19
// Created using:
// - Obsidian (v0.14.15)
// - the Obsidian Dataview plugin (v0.5.36)

let uniqueKeyArray = [];

for (let file of dv.pages().file){
	for (let key of Object.keys(file.frontmatter)){
		
		// Check whether we've already captured this key in our array
		let i = null;
		i = uniqueKeyArray.findIndex((k) => k.fieldName === key);
		
		// If we haven't encountered this key before, push an
		// object with its key and intialized count to the array
		if (i === -1){
			i = uniqueKeyArray.push({fieldName: key, count: 0}) - 1;
		}
		
		// increase the running count for this unique key
		uniqueKeyArray[i].count++;
	}
}

// Create a table with "Unique Key" and "Key Count" headers from
// the array, sorting first alphabetically (ascending) then by
// count (descending). This puts keys with only capitalization
// differences together (at least in US English) so we can quickly
// see which version is more common.
dv.table(["Unique Key", "Key Count"], uniqueKeyArray
	.sort((a, b) =>
		a.fieldName.localeCompare(b.fieldName) || b.count - a.count)
	.map(k => [k.fieldName, k.count]));

As written, this will count every instance of a YAML field, even if it’s used multiple times in the same file.

I might eventually display the file names of anomalies in place of their “1” counts, but it’s pretty straightforward to search for a YAML field name once I know it exists, so I’m not rushing to do it. If you need that implementation but are new to coding and could use some help, let me know and maybe it will jump up my to-do list! My own coding skills are a teensy bit rusty, plus I started working with DataviewJS only yesterday, so if you have any suggestions or corrections I’d love to hear from you.

12 Likes

Well, I wanted to edit my reply above but am having problems editing it! Of course I realized only after I hit the “Reply” button that the following statement is just wrong:

As written, this will count every instance of a YAML field, even if it’s used multiple times in the same file

It seems to get very confused straight away if there are any indented keys in the frontmatter, omitting the indented key as well as both adjacent keys…I think? Clearly I have more testing to do. It will also only count one instance of a YAML field in a file, which is probably fine but contradicts what I said earlier. I would also like it to better handle nested keys, or other unusual YAML variations, but I don’t really know where to begin to learn about those–feel free to point me to any resources you know about funky YAML syntax that folks use in Obsidian!

I would really love it if the plugin exposed the keys themselves for regular queries, but I don’t know how many people suffer from my compulsion to tidy up YAML. I might have to teach myself to build a plugin just for auditing metadata in general!

If my editing functionality issue resolves, I will update my reply and remove this post to keep things uncluttered.

EDIT: of course it’s letting me edit this post and not the one above even though it hasn’t been that long (and didn’t let me edit even right after)…ugh.

3 Likes

Thanks so much for sharing this! @DeutscheGabanna and I were working on something similar, but for all DV keys/fields, not just ones in the frontmatter. Really neat to see an example for just frontmatter!

A couple things I learned from that thread:

  • For inline fields at least, dataview will essentially double-count any with capitalization or punctuation because it silently adds a normalized all-lower-case-dashes-in-place-of-spaces-ignore-other-punctuation version of the key to the page. Does it do that for frontmatter too?
  • I found a Map more intuitive than an array holding an object for the work you’re doing with uniqueKeyArray, but I haven’t experimented with making a dv.table of a map yet.
  • At the bottom of the code snippet in this post there’s code to do the displaying of filenames with keys that show up less than 3 times. I would probably change it to use localeCompare in my sorts now that I know about that thanks to your post!

Thanks again for sharing!

2 Likes

Ah thanks, I am absolutely going to check out your version!!!

  • I do the frontmatter-only version because I use inline keys for lazy description lists :smiley:…for now. I got the idea from other people, but I can’t find a link anywhere for the life of me.
  • I actually did several versions bouncing between different formats for holding the data, but my primary motivation was being rusty with JavaScript; I just needed a version that catered to the things I remember better :sweat_smile:. I would like to explore options that are more straightforward, so I REALLY appreciate you providing links and feedback!
  • localeCompare is pretty great :grin:

I want to iterate more on this soon, but I’m pretty pleased with what I have for my first dataviewjs block ever :slightly_smiling_face:.

2 Likes

I forgot to answer your question: for frontmatter, capitalization and punctuation differences are all counted separately (at least in my snippet)! I tested this with the following keys (all brand-new to my vault and placed together in one file’s YAML), and all of them were treated as unique and each was only counted once: catch:, Catch:, mind:, mind!:, head space:, head-space:, and headspace:.

1 Like

Hello, in my vault i have a folder called work here i create one note for each case i’m working. Inside those notes/cases I create a task list with dates like this - [ ] Do something [🗓️:: 2022-05-23].
Today i use this query to filter my tasks:

dv.taskList(dv.pages('"Notes/Work"')
.sort(p => p.file.name, 'asc')
.file.tasks
.where(t => !t.completed))        

My question is:

  1. Can i render task list where i filter only the tasks with [🗓️:: 2022-05-23] maker?
  2. Can i order this list by date of the marker [🗓️:: 2022-05-23] ?
  3. Can i render a list in this parameters: [ ] DATE: LINK_FOR_THE_NOTE
2 Likes

Dataview as of recently supports that emoji notation for certain task fields without the :: to be compatible with the Tasks plugin. If using that shorthand, the calendar/dates emoji turns into a field called due so you can write things like .where(t => t.due) or .sort(t => t.due, 'desc'). I don’t know whether it’ll work like that with your formatting - you’ll have to experiment!

I don’t understand your question 3 - could you elaborate a little more?

Now it renders like this:

image

And i want to render like this: