Hello,
I am trying to organize my workshop/video course material with Obsidian and DataviewJS and it worked pretty good.
My material consists of
- courses
- chapters
- lessons
- chapters
A chapter note has outgoing links to lessons and contains a dataviewJS overwiew of all tasks in the linked lessons.
This is how I create the list of tasks:
var lessonfolder = "_RMKA/lessons";
const olessons =
// all outgoing notes
dv.current().file.outlinks
// only those below the lesson folder
.filter(f => f.path.startsWith(lessonfolder))
// make page object from link
.map(f => dv.page(f));
for (let i = 0; i < olessons.length; i++) {
let lesson = olessons[i]
let tasks_total = lesson.file.tasks.length
let tasks_open = lesson.file.tasks.where(t => !t.completed).length
let lesson_number = i + 1
dv.header(3, "📖 " + lesson_number + ". " + lesson.file.name)
dv.paragraph(" (" + (tasks_total - tasks_open) + " von " + tasks_total + " erledigt)")
dv.taskList(lesson.file.tasks, false);
}
Well… that’s almost good. The big drawback of this approach is that the Obsidian templates I am using contain the complete JS code which makes it very hard to maintain it. Whenever I want to change the code, I have to change all notes.
Then I discovered the customJS plugin. WOW !
I think that definitely can solve my problem.
But I am struggling…
It seems that I cannot create HTML elements from inside of the JS class.
That’s the class chapterLessons
. It’s almost the same code, with little differences:
- the class
ChapterLessons
holds the methodgetLessonTasks
- instead of dv.current(), the function uses
chapter
as argument - because I am in a 2rd party plugin, I create the dataview API object with
let dv = DataviewAPI
class ChapterLessons {
getLessonTasks(chapter) {
let dv = DataviewAPI;
//Create a table with all notes linked from "chapter" which are in the folder "lessons".
var lessonfolder = "_RMKA/lessons";
// all outgoing notes
const olessons =
// all outgoing notes
chapter.file.outlinks
// only those below the lession folder
.filter(f => f.path.startsWith(lessonfolder))
// create a page object from the link object
.map(f => dv.page(f));
for (let i = 0; i < olessons.length; i++) {
let lesson = olessons[i]
let tasks_total = lesson.file.tasks.length
let tasks_open = lesson.file.tasks.where(t => !t.completed).length
let lesson_number = i + 1
dv.header(3, "📖 " + lesson_number + ". " + lesson.file.name)
dv.paragraph(" (" + (tasks_total - tasks_open) + " von " + tasks_total + " erledigt)")
dv.taskList(lesson.file.tasks, false);
}
}
}
Then I replaced the JS code in the note with that line:
const {ChapterLessons} = customJS;
ChapterLessons.getLessonTasks(dv.current());
That should do the trick.
But it shows this error in the note:
Evaluation Error: TypeError: dv.header is not a function
at ChapterLessons.getLessonTasks (scripts/js/ChapterLessons.js:49:7)
at eval (eval at <anonymous> (plugin:dataview), <anonymous>:8:16)
at DataviewInlineApi.eval (plugin:dataview:18619:16)
at evalInContext (plugin:dataview:18620:7)
at asyncEvalInContext (plugin:dataview:18630:32)
at DataviewJSRenderer.render (plugin:dataview:18651:19)
at DataviewRefreshableRenderer.maybeRefresh (plugin:dataview:18235:22)
at t.e.tryTrigger (app://obsidian.md/app.js:1:695499)
at t.e.trigger (app://obsidian.md/app.js:1:695432)
at t.trigger (app://obsidian.md/app.js:1:2028169)
I tried to tackle the error down by commenting lines; when I omit header
and paragraph
, the error in the note disappears, but the Obsidian developer console throws an error:
plugin:dataview:19208 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'createEl')
at DataviewApi.taskList (plugin:dataview:19208:39)
at ChapterLessons.getLessonTasks (scripts/js/ChapterLessons.js:51:7)
at eval (eval at <anonymous> (plugin:dataview:1:1), <anonymous>:8:16)
at DataviewInlineApi.eval (plugin:dataview:18619:16)
at evalInContext (plugin:dataview:18620:7)
at asyncEvalInContext (plugin:dataview:18630:32)
at DataviewJSRenderer.render (plugin:dataview:18651:19)
at DataviewRefreshableRenderer.maybeRefresh (plugin:dataview:18235:22)
at t.e.tryTrigger (app.js:1:695499)
at t.e.trigger (app.js:1:695432)
Now tasklist
seems to have a problem.
I am completely lost now and a bit frustrated…
Can somebody point me into the right direction? What am I doing wrong?
Thanks a lot!
Simon