I have searching here and there for a way to embed images into an Obsidian DQL view. It took me few hours of experimenting, trial and error. Finally, got two ways of displaying images in views.
Mine is an Obsidian vault implementation of papers. I wanted it to have the same feel as the Movies or the Books vault, examples that are very well known. In those two cases, images render easily because they have the http://
or https://
link form. With local images is more challenging given the fact we are working with local addresses and relatives paths with respect to the vault root.
First, a clarification: local images render right away in dataview by using the absolute path of the image. In Linux would be: file:////home/user/obsidian/papers/Extras/Images/image001.png
. In macOS would be similar. So, the YAML property would show like this:
---
poster: file:////home/user/obsidian-git/papers-vault/store/Pasted%20image%2020231027152442.png
---
The dataview query to transclude the image from within the view would be:
table without id
( "![]("+ poster + ")" ),
file.link as Title
from "Papers"
where contains(file.etags, "#ImageWithAbsolutePath")
You should be able to see the transclusion code to embed the image. It’s easy but has a big problem: it will work in only in one machine! And of course, forget about synchronizing to an iPad or iPhone.
What works
What I found what works with rendering local images in dataview queries is:
- Entering the local image filename as a text;
- Entering the local image filename as a link.
I like more the second because I could click on the link in the YAML properties and I will be able to see the image.
For Case 1 (image as a text):
The YAML property for the image would be:
poster: Pastedimage20231027144730.png
Note that I have removed the spaces of this image while I was debugging the solution. If the image contains spaces in its filename it will only render in dataview if we physically enter the spaces instead of %20
. An image containing %20
in its filename will not render unless is written in absolute path mode.
The DQL for the first case (image file as text) is:
table without id
poster,
meta(link(poster)),
embed(link(meta(link(poster)).path)),
file.link as Title
from "Papers"
where contains(file.etags, "#ImageAsText")
I am providing the step by step of the rendering formula. If you run it, you should be able to see all the low level output:
Look at the path that results from applying the function meta()
. It makes reference to the relative path where the image lives.
For Case 2 (image as a link):
The YAML property for the image would be:
poster: [[poster-20231026193936.png]]
Note the square brackets. I like this approach because I could click on it and open the image. Sort of double-check. The DQL would be:
table without id
poster,
link(poster),
meta(link(poster)),
link(meta(link(poster)).path),
embed(link(meta(poster).path)),
file.link as Title
from "Papers"
where poster != null
You can see that the only difference is the presence of the function link()
over the YAML property. The rendering would be similar to the 1st case.
Just pay attention to how the image link, this time, es clearly visible.
I believe this code could be simplified further by checking if the property is a link or text.
Enjoy!