I’ve built a dvjs view and managed to add a lazy loading feature to it.
As this can be useful for all compute-intensive dvjs views (and dql queries), I thought I’d extract its logic into a single file for easier use. Here it is:
const viewObserver = new IntersectionObserver((entries) => {
entries.map((entry) => {
if (entry.isIntersecting) {
viewObserver.unobserve(entry.target);
if (typeof input === 'string') {
dv.execute(input)
} else {
input()
}
}
});
});
viewObserver.observe(dv.container)
To use it you’ll need to save this in a .js file somewhere in your vault. You can name it the way you want (mine is saved at this path inside my vault _js/lazyload.js
). Then to “convert” your codeblock and make it lazy loaded, you’ll need to do 2 things:
- Put all the code from your codeblock inside a function (don’t forget to make it
async
if needed) - Call the view to lazyload your function
So for example, you should go from this:
```dataviewjs
const amountOfImages = 3;
const attachmentFolderPath = app.vault.getConfig("attachmentFolderPath");
const imageFiles = app.vault
.getFiles()
.filter(file => {
return file.extension !== 'md'
&& file.parent.path.startsWith(attachmentFolderPath)
})
dv.list(dv.array(imageFiles)
.sort(() => 0.5 - Math.random())
.limit(amountOfImages)
.map(file => dv.func.embed(dv.fileLink(file.path))))
```
P.S 1: The original code from this codeblock was taken from here: obsidian_dataview_example_vault/20 Dataview Queries/Display random images from a path.md at main · s-blu/obsidian_dataview_example_vault · GitHub (fantastic resource btw)
P.S. 2: Don’t try using it on iPad, it crashes the app (for unkown reasons)
to this:
```dataviewjs
function f() {
const amountOfImages = 3;
const attachmentFolderPath = app.vault.getConfig("attachmentFolderPath");
const imageFiles = app.vault
.getFiles()
.filter(file => {
return file.extension !== 'md'
&& file.parent.path.startsWith(attachmentFolderPath)
})
dv.list(dv.array(imageFiles)
.sort(() => 0.5 - Math.random())
.limit(amountOfImages)
.map(file => dv.func.embed(dv.fileLink(file.path))))
}
await dv.view("_js/lazyload", f)
```
From now on, the code within your function will not be triggered until the code block is visible in your window, and yes, it works with closed callouts!
Dataview DQL support
This solution works with dataviewjs out of the box. Now If you want to do the same with your dataview queries, you’d need to do the following:
- Verify that you you have
Enable JavaScript Queries
enabled in dataview’s settings - Change
dataview
todataviewjs
at the top of your code block - Instead of encapsulating your code in a function, you will want to convert your entire DQL code into a string and store it in a variable:
from this:
```dataview
LIST
FROM ""
WHERE file.size = 0
```
to this:
```dataviewjs
const dql = `LIST
FROM ""
WHERE file.size = 0`
await dv.view("_js/lazyload", dql)
```
N.B. Obsidian already does a lazy loading of the file content, so if you have a long file and your code block is at the very bottom, it wouldn’t have been loaded into the DOM in the first place.