1

Running into an issue trying to pull out values from the frontmatter of weekly notes in ObisdianMd and render a chart using DataviewJS and Chart.js.

The frontmatter for each weeks note looks like this...

---
Year: 2023
Week: 10
Time: 22:44
Tags: weekly_journal
Word: "Bullshit"
Mind:
  - 1
  - 2
  - 2
  - 1
  - 3
  - 4
  - 0
Body:
  - 1
  - 2
  - 2
  - 1
  - 3
  - 4
  - 0
Alias: "Stressed and tired"
---

Specifically I am pulling out the Mind and Body arrays, calculating the average of each, and plotting the results on a line chart (X = week, y=average).

Everything works as expected apart from when I attempt to define the y dataset on the graph using the calculated average from the arrays. This is when I encounter the TypeError: n.push is not a function error.

This code renders a chart correctly for the average weekly mind score when using dummy data (I have cut out a lot of the chart config options for clarity)...

const pages = dv.pages(`#weekly_journal and -"3000 - Templates"`)
const data = pages.map(b => average(b.mind))
const labels = pages.map(b => b.week)

const chartData = {
    type: 'line',
    
    data: {
        labels: labels,
        datasets: [
            {
                label: 'Mind',
                labelColors: true,
                data: [1, 2, 3],
                backgroundColor: [`rgba(255,255,255,0.9`],
                borderColor: [`rgba(210,105,30 ,0.3`],
                borderWidth: 2,
                borderDash: [3,5],
                tension: 0,
                pointStyle: `rectRounded`,
                stepped: false,
            },
        ],
        
    },

this.container.classList.add('chart-container')
window.renderChart(chartData, this.container)

function average(arr) {
    if (arr.length === 0) {
        return 0;
    }
    const sum = arr.reduce((a, b) => a + b);
    const avg = sum / arr.length;
    return Math.round(avg);
}

However, when I replace the line data: [1, 2, 3] with the data: data, expecting it to use the average calculated by const data = pages.map(b => average(b.mind)) it throws the TypeError: n.push is not a function error.

outputting the data const to the console confirms that it is an array...

values: Array(2)
0: 11
1: 10
length: 2

I am guessing it has something to do with the array data but beyond that I am stuck.

1 Answers1

1

Answering my own question. Adding the following resolved the issue...

const data = pages.map(b => average(b.mind))
const dataArray = data.values
const flatData = dataArray.reduce((acc, val) => acc.concat(val), [])

The Chart.js was getting upset because the array wasn't flattened.

The complete code looks like this for anyone wondering...

// Query to pull out journals
const pages = dv.pages(`#weekly_journal and -"3000 - Templates"`).sort( k => k.week, `asc`)
const data = pages.map(b => average(b.mind))
const dataArray = data.values
const flatData = dataArray.reduce((acc, val) => acc.concat(val), [])

const labels = pages.map(b => b.week)


// define Chart Data
const chartData = {
    type: 'line',
    
    data: {
        labels: labels,
        datasets: [
            {
                label: 'Mind',
                labelColors: true,
                data: flatData,
                backgroundColor: [`rgba(255,255,255,0.9`],
                borderColor: [`rgba(210,105,30 ,0.3`],
                borderWidth: 2,
                borderDash: [3,5],
                tension: 0,
                pointStyle: `rectRounded`,
                stepped: false,
            },
        ],
        
    },

    options: {
        maintainAspectRatio: true,
        width: `50%`,

        plugins:{
            title: {
                display: true,
                text: `Mind`,
                align: `center`,
                color: [`rgba(255,255,255 ,1`], 
                padding: {
                    top: 10,
                    bottom: 0
                }
            },
            subtitle: {
                display: true,
                text: `This Years Mental Status`,
                align: `center`,
                padding: {
                    top: 0,
                    bottom: 20
                }
            },
            legend: {
                display: false,
            }
        },

        scales: {
            y: {
                min: 0,
                max: 5,
                
                grid: {
                    display: true,
                    color: [`rgba(210,210,210 ,0.1`],
                    width: 1
                },
                title: {
                    display: true,
                    text: `Mind`
                },
                ticks: {
                    display: true,
                    padding: 6,
                    colour: [`rgba(210,0,0,1`],
                    stepSize: 1
                }
            },
    
            x: {
                min: 0,
                max: 7,
                
                grid: {
                    display: true,
                    color: [`rgba(210,210,210 ,0.1`],
                    width: 1
                },
                title: {
                    display: true,
                    text: `Week`,
                    padding: {
                        bottom: 20
                    }
                }
            },

        },
        animation:{
            animation: true,
            duration: 500,
            easing: `linear`            
        },

        layout:{
            padding: {
                left: 60,
                right: 60,
                top: 20,
                bottom: 10          
            }
        
        
        }
        
    }

}


// Render Chart
this.container.classList.add('chart-container')
window.renderChart(chartData, this.container)



// Function to average and round the arrays
function average(arr) {
    if (arr.length === 0) {
        return 0;
    }
    const sum = arr.reduce((a, b) => a + b);
    const avg = sum / arr.length;
    return Math.round(avg);
}