Get colors with obsidian charts dataviewjs query

Not sure if this is the place to post - I started using charts in dataviews, but was quite upset that colors did not work. Wonder if more have this problem.

I found a post here in the forum, that had a solution: No colors with Obsidian Charts dataviewjs query - #2 by oopzzozzo.

But the solution did not work for me. After playing around with the approach, I found the workaorund velow. As the above thread is closed, I’m posting my work around here.

Colored charts with dataviews are pretty cool - so I’m glad it works now. I’d think more people here would use it. So I wonder that the workaround is still needed - maybe some else has some other proposals for a fix.

See here’s an example that works for me. The arrayToString function is a hack, but works for me, even with numbers instead of strings. Probably a JSON print could also help - that didn’t want to rely on other stuff.

Here’s the dataview:

```dataviewjs
// just a helper function
function arrayToString(arr) {
    var str = `[`;
    var start = true;
    for (const element of arr) {
        if (start) {
            str = str+`'`+element+`'`;
            start = false;
        } else {
            str = str+`, '`+element+`'`;
        }
    }
    str = str + `]`;
    return str;
}
// I want to set stuff dynamically, so I need to work with variables
const labelsString = arrayToString(['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange']);
const dataString = arrayToString([12, 19, 3.7, 5, 2, 3]);
// Using variables inside a string for dv.paragraph did not work for me - instead I create the whole string here, and then pass it as a variable
const format =`\`\`\`chart
	type: 'bar'
	labels: `+labelsString+`
	labelColors: true
    beginAtZero: true
	series:
	- data: `+dataString+` 
    - title: Beispiel Wort
\`\`\``

dv.paragraph(format)

``` (end of dataviewjs)

Thanks Zane for sharing your findings. Here’s an iterative improvement on your solution. At this point it should probably become a plugin but I’ve spent too much time procrastinating. Maybe I’ll do it later if someone doesn’t beat me to it.

  • simplify converting arrays to strings
  • add a class to make it slightly more declarative
  • add the class to the window object so it can be used in subsequent dataviewjs blocks without defining it over and over again.
```dataviewjs
window.DVChartBuilder = class {
    constructor(type = 'bar') {
        this.type = type;
        this.labels = [];
        this.datasets = [];
        this.options = {};
    }

    addLabels(labels) {
        this.labels = labels;
        return this;
    }

    addDataset(title, data, colors = []) {
        this.datasets.push({
            label: title,
            data: data,
            backgroundColor: colors.length ? colors : undefined, // optional color
        });
        return this;
    }

    setOption(key, value) {
        this.options[key] = value;
        return this;
    }

    setWidth(width) {
        return this.setOption('width', width);
    }

    setFill(fill) {
        return this.setOption('fill', fill);
    }

    setBestFit(enabled, title = "Line of Best Fit", lineNumber = 0) {
        this.setOption('bestFit', enabled);
        if (enabled) {
            this.setOption('bestFitTitle', title);
            this.setOption('bestFitNumber', lineNumber);
        }
        return this;
    }

    setSpanGaps(spanGaps) {
        return this.setOption('spanGaps', spanGaps);
    }

    setTension(tension) {
        return this.setOption('tension', tension);
    }

    setBeginAtZero(beginAtZero) {
        return this.setOption('beginAtZero', beginAtZero);
    }

    setLegend(legend) {
        return this.setOption('legend', legend);
    }

    setLegendPosition(position) {
        return this.setOption('legendPosition', position);
    }

    setIndexAxis(axis) {
        return this.setOption('indexAxis', axis);
    }

    setStacked(stacked) {
        return this.setOption('stacked', stacked);
    }

    setAxisModifier(axis, options) {
        if (!this.options[axis]) {
            this.options[axis] = {};
        }
        Object.assign(this.options[axis], options);
        return this;
    }

    toChartFormat() {
        const arrToStr = (input) => `[${input.join()}]`;

        const format = `\`\`\`chart
type: ${this.type}
labels: ${arrToStr(this.labels)}
labelColors: true
${this.datasets.map(dataset => `
series:
   - title: "${dataset.label}"
     data: ${arrToStr(dataset.data)}`).join('')}
${Object.entries(this.options)
    .map(([key, value]) => {
        if (typeof value === 'boolean') return `${key}: ${value}`;
        if (typeof value === 'object') return `${key}: ${JSON.stringify(value)}`;
        return `${key}: ${value}`;
    }).join('\n')}
\`\`\``;

        return format;
    }

    renderToDataview(dv) {
        dv.paragraph(this.toChartFormat());
    }
};


const chart = new DVChartBuilder()
    .addLabels(["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"])
    .addDataset("Sales", [10, 20, 30, 40, 50], ['#FF5733'])
    .addDataset("Revenue", [5, 15, 25, 35, 45], ['#33FF57'])
    .setWidth("40%")
    .setFill(true)
    .setBestFit(true, "Sales Best Fit", 0)
    .setSpanGaps(true)
    .setTension(0.3)
    .setBeginAtZero(true)
    .setLegend(false)
    .setLegendPosition("bottom");
chart.renderToDataview(dv);