I’m trying to convert a script that I use in daily notes as a re-usable script. This script generates a pie chart based on the notes that I have in the respective daily note markdown file. Below is how I use my code, and I’m able to successfully execute it if I directly write it in a code block in the daily note. But when I try to re-use it using dv.view(), I’m getting error, only for the code that uses Obsidian Charts.
Things I have tried
dv.view("Scripts");
view.js file in Scripts folder:
const chartData = {
type: 'doughnut',
data : {
labels : labels,
datasets : [ {
backgroundColor : randColors,
data : data
} ]
}
}
dv.el("h4", "Task Type Chart");
window.renderChart(chartData, this.container);
I’m getting the below error :
Dataview: Error while executing view ‘Scripts/view.js’.
TypeError: Cannot read properties of undefined (reading ‘createEl’)
Using dv.view() is a better option for reusability, but you need to pass the proper data to the script file. It’s a matter of a variable scoping, and passing along what’s needed for the dv.view() to function properly.
Put another way, instead of just doing dv.view("Scripts"), you need to do something like dv.view("Scripts", data) (or even more elaborate versions like dv.view("Scripts", { data: myDataVariable, type: "line" }) ). The data would then be available within the script through the input variable.
I consider dv.view() a better option since it becomes a static call wherever you insert it, while it still allows for the actual query to be dynamic.
For example in my daily notes I’ve got a call to await dv.view("_js/journalHeaderNav") which builds a header to navigate my journal entries. I always want to have a header, but how I want that to look might change. Using dv.view() I can now just change the _js/journalHeaderNav.js file, and all pages linking (through the dv.view()call) will be updated.
I’ve not used dv.executeJs, and I can see a use if you’re generating the query somehow. It could potentially be useful (from my point of view), if you “import” the source into it (like you did using await dv.io.load(...)). Like if you have another note holding the actual query, and then load that note, and use it in a call to dv.executeJs. Then again, that is the functionality provided by dv.view(). Differences does come down to variable scoping, and what’s available in either version. I’ve not looked a whole lot into that, but I feel that the the dv.view() is the cleaner solution, when javascript is the query language.
A similar approach could possible be used by dv.execute() if you’re more into DQL. That it, let another note hold the actual query, and then in the pages where you want to use that query, you do some variant of dv.execute() where the source is lifted/imported from the query note.