What I’m trying to do
Using the Charts and Dataview community plug-ins I would like to firstly, write a Dataview JS query that lists number of occurrences of certain Dataview inline field keys in the current Obsidian note and secondly, plot the table data into a horizontal bar chart.
I’m using:
- Obsidian.md 1.7.6
- Charts 3.9.0
- Dataview 0.5.67
My desired end result is a Charts graph. If I understand the manual about Dataview integration correctly I have to use a Dataview JS query, it can’t be a Dataview Query Language (DQL) query. JavaScript is foreign to me so I got myself started with at least a DQL query that starts off on the right path.
Things I have tried
Dataview Query Language
Given a Markdown file that has the Dataview inline field key status
in multiple places in the note body where each field value is an emoji with a status name:
(status:: 🛑 Not Started)
(status:: 🛑 Not Started)
(status:: 🛑 Not Started)
(status:: 🛑 Not Started)
(status:: 🔃 In Progress)
(status:: 🔃 In Progress)
(status:: ✅ Ready)
(status:: ✅ Ready)
(status:: ✅ Ready)
And given the following DQL query:
```dataview
table length(rows) as "Count"
where file.path = this.file.path and status
flatten status
group by status as "Status"
```
Dataview renders a table like so:
This gives me a table but it’s not a table that Charts can use. I tried approaching this also from the Charts side of things as follows.
Charts
Given the following Markdown table per Chart’s “Chart from Table” documentation I can add a block ID right underneath the table:
| Status | Count |
| -------------- | ----- |
| ✅ Ready | 3 |
| 🔃 In Progress | 2 |
| 🛑 Not Started | 4 |
^my-table
Which renders like so:
And given the following Chart definition:
```chart
type: bar
id: my-table
indexAxis: "y"
```
I get a horizontal bar chart rendered like so:
Glue
What I’m missing is arguably the most difficult part, a translation of above DQL query into Dataview JS and a Chart code block that uses that Dataview JS query to render a graph.
I’ve asked the Chat-GPT 4o mini
Large Language Model for its take on how to convert this into Dataview JS and Chart syntax. Screenshot of the result here. It says, here’s how to get going:
// Get all pages containing the "status" field
const pages = dv.pages('"#"').where(p => p.status);
// Initialize an object to store the count of each status
let statusCounts = {};
// Loop through each page to count occurrences of each status value
pages.forEach(page => {
// Flatten the status values (in case there are multiple on a single page)
const statuses = page.status.flatten();
// Loop through each status and increment the count
statuses.forEach(status => {
if (statusCounts[status]) {
statusCounts[status]++;
} else {
statusCounts[status] = 1;
}
});
});
// Convert the counts into an array that can be used by the Chart plugin
const chartData = Object.entries(statusCounts).map(([status, count]) => {
return { label: status, value: count };
});
// Render the chart with the data
dv.chart("bar", chartData, {
x: "value", // Values are on the x-axis
y: "label", // Status labels are on the y-axis
horizontal: true, // This makes the chart horizontal
title: "Status Count" // Title for the chart
});
This correctly throws a TypeError: dv.chart is not a function
. As for the rest of this snippet I can’t even begin to wrap my head around how I’d approach this.
How do I render a graph from a Dataview JS query that does what the DQL query above does?
I’d gladly take any help on this. Thanks!