DataviewJS Snippet Showcase

Not quite sure why your currently reading is at the bottom. But if you have more books in that than in your unreads, that might have something to do with it.

Thank you for sharing. Yeah I can’t figure it out either. I do have more that are unread than currently reading. Have you made a table for books that you have read?

EDIT: I figured out shat the problem was with is being reversed. I was using a Emoji in my title which was causing it to reverse.

I also ran into this thread which might help you to clean up the code by using this plugin. DataviewJs - Code reuse: common place for scripts

I still don’t know enough to get it to work, but hopefully this will be helpful for you.

Automatic inlinks to a note

I’ve been holding off on submitting a few of my snippets here just to make sure they’re not a fad… but it’s been a few months now and I have to say one dataviewjs block that’s really improved how I use Obsidian has been having a block that nicely displays all the inlinks to a given file.

This is what it looks like:

And this is the code snippet:

// Nicely Render all the inlinks to the current note on a single line
// Checks if an alias exists for inlinks and will render the alias
// if it exists
//
let myInlinks = [];
for (let inlink of dv.current().file.inlinks){
	if (inlink.path != dv.current().file.path) {
		let inlinkFile = dv.page(inlink.path).file
		let displayName = inlinkFile.aliases ? inlinkFile.aliases[0] : inlinkFile.name
		let fileLink = dv.fileLink(inlinkFile.path, false, displayName)
		myInlinks.push(fileLink)
	}
}
let myInlinksStr = ` **Inlinks**: ${myInlinks.join(', ')}`
dv.paragraph(myInlinksStr)

How it works

  1. Get all the inlinks of the current file
  2. Iterate through them, ignoring any self reference (such as internal header links)
  3. Get the inlink file object to read it’s data
  4. Create a dataview fileLink, using the first inlinks alias as the displayname if there’s an alias.
  5. Push all the fileLinks into an array
  6. Render a comma separated list of the fileLinks with a prefix of Inlinks

I find this significantly helps me flow through my notes and lets me links files an organic way.

My typical journeys might be:

I create a note about a new takeaway place i’ve tried, and link it to my notes on Deliveroo, Chinese Food, Local Takeaways, Cheap Eats etc. Infact, i’ve more or less forgone using tags at all now in preference of notes as tags since I find they serve the same purpose with more utility.

By using the dataviewjs I can have more control over the format like using the alias for example. I often use aliases for my Map of Content (MOC) notes.

The only minor issue i’ve had that’s probably worth mentioning is on the new creation of a file, the parent inlink won’t automatically show since it’s not present in the file.inlinks array. But if I really need this immediately, I can reload Obsidian and it’ll update.

11 Likes

Render metadata if it exists

Another fairly simple example of using the dataviewjs cobeblock to style data I find useful is note descriptions. In my default note template I have a description key to give a summary of what the notes about. Depending on what the notes about, this can be useful, other times it’s not relevant.

# {{title}}

``` dataviewjs
let page = dv.current();
if (page.description){
dv.paragraph(
	"**Description:** " + page.description
)
}
\```

Originally, i’d have a line with **Description:** Notes about {{title}} just under the note title. But then I was getting annoyed by how redundant this was so I just shortened it to **Description:** which I wasn’t getting on with. When notes didn’t need it, i’d either remove it, which I don’t like, to me, my note templates are there so I can immediately focus on outputting the content of the note and minimising the amount of time or thought I spend on styling… but If I didn’t delete it, on revisiting the note I’d catch myself thinking about what this notes description was and trying to “complete” this seemingly incomplete prompt.

When I started adding YAML to my notes, I liked the idea of notes having a description field, since I could potentially see creating query based tables that displayed this field. So I tried just adding an inline metatag description::, only when needed, but to me this just looked a bit ugly and I would habitually default to Description::.

With the dataviewjs plugin I can have my cake and eat it. Now in my daily note I have an empty description metatag that will render once it has a value. Letting me focus on the content, not the styling.

I quite like this design pattern, and can see myself reusing it for other metatags. I have a few different note templates which I’d like to keep to a minimum since alot of them share the same components that I continue to evolve and maintain, I can see conditional rendering using the metadata as a method of keeping a few flexible note templates that have consistent styling.

4 Likes

Keeping notes on Beers

Final example i’d like to showcase, is how I use dataviewjs for styling in my Beer notes.

I’m an occasional beer drinker, love trying different ones, always forget which I like and where I got them. For ages I wanted to be able to have a personal way of keeping track of what I liked and disliked, but at the same time, have it quick to do, otherwise I won’t do it. After a bit of refining i’ve settled on a note template that works well for me that looks something like this:

With the code looking like this:

---
type: beerCard
Rating: 9
ABV: 6.5%
Cost: £
Producer: Pressure Drop
Type: Porter
Bought-From: "[[Beer and Burger]]"
Tasting-Notes: "Great porter, really balanced flavour, not to sweet and can taste the coffee and chocolate. Really easy drinker. Would definitely get again"
Image: "[[IMG_20220107_230609.jpg]]"
Description: "Roasty, Coffee Chocolate"
---

Tags: #products/beer 

\``` dataviewjs
// Nicely Render all the inlinks to the current note on a single line
// Checks if an alias exists for inlinks and will render the alias
// if it exists
//
let myInlinks = [];
for (let inlink of dv.current().file.inlinks){
	let inlinkFile = dv.page(inlink.path).file
	let displayName = inlinkFile.aliases ? inlinkFile.aliases[0] : inlinkFile.name
	let fileLink = dv.fileLink(inlinkFile.path, false, displayName)
	myInlinks.push(fileLink)
}
let myInlinksStr = `**Inlinks**: ${myInlinks.join(', ')}`
dv.paragraph(myInlinksStr)
\```
**Oulinks**: [[_MOC Products|Products]], [[Beer Tasting Notes]]

# Fashion Porter

``` dataviewjs
let page = dv.current();
dv.paragraph(
	"**Description** " + page.Description
)
\```

![[IMG_20220107_230609.jpg|left|250]]
\``` dataviewjs
let page = dv.current();

dv.paragraph(
	"**Rating:** " + page.Rating + "\n"
	+ "**ABV:** " + page.ABV + "\n"
	+ "**Cost:** " + page.Cost + "\n"
	+ "**Type:** " + page.Type + "\n"
	+ "**Producer:** " + page.Producer + "\n"
	+ "**Bought From**: " + page["Bought-From"] + "\n"
	+ "**Tasting Notes**: " + page["Tasting-Notes"]
)
\```

So when I create a new beerCard note, I just update the YAML and take a quick picture of the beer on my phone and import into the note.

And since it’s all in the metadata… I get to create a pretty dataview table like this:

N.B. If you look close you’ll see a few minor inconsistencies in the code snippets across my showcases, since my templates and queries get a bit more evolved. Ultimately Obsidian is a tool for capturing knowledge for me so I try not to be too disciplined or care too much about the underlying consistency unless I have a reason too.

11 Likes

Hi,
I have been working on my daily and weekly notes and I would like to share my snippets that I use for my daily and weekly review.

Although dataview dynamic table are great, I think a static tables are useful to review the notes that I worked every day. Furthermore, are useful to plan the next day or when I’m doing the weekly review, and also I found it useful to do a project inform.

First, I use dataviewjs to create a dynamic table for every day and then convert to a Markdown table using Dataviewjs script for creating Markdown table.

The script will show the table like this:

image

Or if you prefer a collapsible ad-note:

To create a static table, you can copy the result and paste wherever you want:

image

Here are the code:

4 Likes

For weekly review I use a script very similar to the daily review but grouped by day.

image

After copy the table:

image

Here is the code:

Hi. I just wanted to share a simple way I found to make dataviewjs render local images on both apps, desktop and mobile.

const filePath = (file) =>
    file.startsWith("http") ?
        file :
        app.vault.adapter.getResourcePath(file)

dv.table(["Name", "Thumbnail"], dv.pages("#Movie")
    .sort(item => item.file.name, 'asc')
    .map(item => [
        item.file.link,
        `![](${filePath(item.thumbnail)})`
    ])
)

The filePath() function just checks if the string starts with http, and converts it to an internal link otherwise, using the vault.getResourcePath function.

A minor inconvenience is that getResourcePath needs the full path to the images. So attachments/example.png works, but just example.png, ![](attachments/example.png) or ![[example.png]] doesn’t. But It can easily be upgraded with more checks to parse wiki links, markdown formatted links, etc.

3 Likes

Display notes with Trello links and click link to notes

Note links will be loaded on demand, thus keeping the table fairly lightweight.

You will, of course, need the Trello plugin installed.

const openButton = (boardandcard, note) => {
	const button = this.container.createEl('button', {"text": "𝌡"});
    button.addEventListener('click', async(e) => {
        e.preventDefault();
		[board, card] = boardandcard.split(";")
		app.plugins.plugins['obsidian-trello'].
			api.getCardFromBoard(board, card).
			forEach((info) => {
				window.location = info.url;
			})
    });
    return button;
}

console.log(dv.current());
dv.table(["Page", "Action"],
	dv.pages('').where(
		p => p.trello_plugin_note_id).sort(
		p => p.file.mtime, "desc").map(
		p => [
			p.file.link,
			openButton(
				p.trello_board_card_id,
				p.trello_plugin_note_id)])
)
1 Like

Hi, don’t know if this is the correct place to post, but i created a plugin that works on top of DataviewJS to display progress for whatever you want to track. Picture says it all i think:

11 Likes

Where can we get this plugin?

Its called “Heatmap Calendar”, search for it on the community plugin list in obsidian

1 Like

Show unresolved links

This snippet allows you to see all your dangling links.
You can configure how many connections each link has to have before it shows up.
You can also exclude existing and non-existing files from showing up.

//how many links a non existing file should have at minimum
const count = 2;

//specify the full path here.
const ignoredExisting = ["your/ignored/notes/here.md"];

//keep these in lower case.
const ignoredNonExisiting = ["your non exisiting notes", "here is note that does not exist"];

let d = {};
function process(k, v) {
  Object.keys(v).forEach(function (x) {
    if(!ignoredNonExisiting.includes(x.toLowerCase())) {
        x = dv.fileLink(x);
        if (d[x]==undefined) { d[x] = []; }
        if(!ignoredExisting.includes(k)) {
            d[x].push(dv.fileLink(k));
        }
    }
  });
}

Object.entries(dv.app.metadataCache.unresolvedLinks)
    .filter(([k,v]) => Object.keys(v).length)
    .forEach(([k,v]) => process(k, v));
    
dv.table(["Non existing notes", "Linked from"],
         Object.entries(d)
         .filter(([k, v]) => v.length >= count)
	     .sort((a, b) => b[1].length - a[1].length)
         .map(([k,v]) => [k, v.join(" • ")]));

(code based on: Is there a way to see backlinks without creating a markdown document? - #3 by JLDiaz)

9 Likes

Could you share an example of the code you used to create this please?

2 Likes

I’m using a Mac, and Dataview is converting “Command” to “Control,” so when I have a hotkey at uses Ctrl-Cmd, it is listed and Ctrl-Ctrl. And more importantly, if it’s Cmd-O, it’s listed as Ctrl-O.

Is there something I could change to have the queries account for the Mac’s command key?

Thanks,
Russell

Hi everybody !

Would you know a method to use emojis as keys inside a dataviewjs query ?
I could write some successful queries using DQL but not with dataviewjs

Somehwere in my vault :

- [ ] [🗝:: value] Text

What I try to do :

let tasks = dv.array(dv.pages().file.tasks)
dv.header(6,tasks[0].🗝)

This doesn’t work and throws an error :

Evaluation Error: SyntaxError: Invalid or unexpected token
[...]

It would be even better if I could have a Yaml setting, such as :

---
filter : 🗝
---

Used in my dataviewjs query :

var filter = dv.current().filter;
let tasks = dv.array(dv.pages().file.tasks)
dv.header(6,tasks[0].filter)

Many thanks in advance for your kind help

Solved by @TfTHacker himself, thank you so much !
For those who would be interested, the solutions are :

let tasks = dv.array(dv.pages().file.tasks)
dv.header(6,tasks[0].["🗝"])

and even the yaml filter thing works,

---
filter : 🗝
---
var filter = dv.current().filter;
let tasks = dv.array(dv.pages().file.tasks)
dv.header(6,tasks[0].[filter])
4 Likes

Generally this works great but for some reason, when I make a new note today I get this error (but it does not happen in the notes I created for all days earlier in this week …):

Evaluation Error: TypeError: Cannot read properties of undefined (reading 'file')
    at eval (eval at <anonymous> (eval at <anonymous> (app://obsidian.md/app.js:1:1444405)), <anonymous>:7:36)
    at DataviewInlineApi.eval (eval at <anonymous> (app://obsidian.md/app.js:1:1444405), <anonymous>:15671:16)
    at evalInContext (eval at <anonymous> (app://obsidian.md/app.js:1:1444405), <anonymous>:15672:7)
    at asyncEvalInContext (eval at <anonymous> (app://obsidian.md/app.js:1:1444405), <anonymous>:15682:32)
    at DataviewJSRenderer.render (eval at <anonymous> (app://obsidian.md/app.js:1:1444405), <anonymous>:16267:19)
    at DataviewRefreshableRenderer.maybeRefresh (eval at <anonymous> (app://obsidian.md/app.js:1:1444405), <anonymous>:15995:26)
    at HTMLDivElement.i (app://obsidian.md/app.js:1:138855)

Oh, but of course a shutdown/re-open of Obsidian fixes this.

:thinking:

Just ignore the above error posting then …

Would love to have this snippet!

1 Like