The ultimate Fabric, Power BI, SQL, and AI community-led learning event. Save €200 with code FABCOMM.
Get registeredCompete to become Power BI Data Viz World Champion! First round ends August 18th. Get started.
Hi everyone,
I'm developing a PowerBI custom visual to draw time series differentiated by a legend.
The problem I'm having is with formatting settings.
What I would like is to have a colorPicker in my formatting pane for each of my series.
Here's what I've already done:
- I created a "colorSelector" object in capabilities.json that will be a Slice for each series colorPicker
- I created a selection for each series using this documentation (Create selections for series)
- I used colorHelper to set the default color for series with colorPalette or find the color of the “colorSelector” object associated with a serie, based on this documentation
- I populated the pane formatting based as much as possible on the barChat example github
I manage to get something but the behavior is bizarre:
- There's a colorPicker for each different series BUT when I change the color, it instantly reverts to its default value.
I think I'm missing some information so that I can properly assign a color to each series and then retrieve them, but I haven't been able to find a solution for several days.
Here's what I think
I'd like to thank anyone who can help me understand the problem I encounter.
Here is the code:
capabilities.json
{
"dataRoles": [
{
"displayName": "Categories",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measures",
"name": "measure",
"kind": "Measure"
},
{
"displayName": "Series",
"name": "series",
"kind": "Grouping"
}
],
"objects": {
"colorSelector": {
"properties": {
"fill": {
"type": {
"fill": {
"solid": {
"color": true
}
}
}
}
}
}
},
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"group": {
"by": "series",
"select": [{
"for": {
"in": "measure"
}
}
]
}
}
}
}
],
"privileges": []
}
settings.ts:
"use strict";
import { formattingSettings } from "powerbi-visuals-utils-formattingmodel";
import { dataSerie } from "./visual";
import FormattingSettingsCard = formattingSettings.SimpleCard;
import FormattingSettingsSlice = formattingSettings.Slice;
import FormattingSettingsModel = formattingSettings.Model;
import ColorPicker = formattingSettings.ColorPicker;
class ColorSelectorCardSettings extends FormattingSettingsCard {
name: string = "colorSelector";
displayName: string = "Data Colors";
slices: FormattingSettingsSlice[] = [];
}
export class VisualFormattingSettingsModel extends FormattingSettingsModel {
colorSelector = new ColorSelectorCardSettings();
cards: FormattingSettingsCard[] = [this.colorSelector];
populateColorSelector(dataPoints: dataSerie[]) {
const slices: FormattingSettingsSlice[] = this.colorSelector.slices;
if (dataPoints) {
dataPoints.forEach(dataPoint => {
slices.push(new ColorPicker({
name: "fill",
displayName: dataPoint.value.toString(),
value: { value: dataPoint.color },
selector: dataPoint.selection.getSelector(),
}));
});
}
}
}
visual.ts:
"use strict";
import powerbi from "powerbi-visuals-api";
import { FormattingSettingsService } from "powerbi-visuals-utils-formattingmodel";
import { ColorHelper } from "powerbi-visuals-utils-colorutils";
import "./../style/visual.less";
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import ISelectionId = powerbi.visuals.ISelectionId;
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
import IColorPalette = powerbi.extensibility.IColorPalette;
import DataViewValueColumns = powerbi.DataViewValueColumns;
import DataViewValueColumnGroup = powerbi.DataViewValueColumnGroup;
import DataViewObjectPropertyIdentifier = powerbi.DataViewObjectPropertyIdentifier;
import ILocalizationManager = powerbi.extensibility.ILocalizationManager;
import { VisualFormattingSettingsModel } from "./settings";
export interface dataSerie {
value: powerbi.PrimitiveValue;
selection: ISelectionId,
color: string;
}
export class Visual implements IVisual {
private formattingSettings: VisualFormattingSettingsModel;
private formattingSettingsService: FormattingSettingsService;
private host: IVisualHost;
private colorPalette: IColorPalette;
private localizationManager: ILocalizationManager;
constructor(options: VisualConstructorOptions) {
this.host = options.host;
this.localizationManager = this.host.createLocalizationManager();
this.formattingSettingsService = new FormattingSettingsService(this.localizationManager);
this.colorPalette = options.host.colorPalette;
}
public update(options: VisualUpdateOptions) {
this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualFormattingSettingsModel, options.dataViews?.[0]);
const dataSeries: dataSerie[] = [];
const series: powerbi.DataViewValueColumnGroup[] = options.dataViews[0].categorical.values.grouped();
const valueColumns: DataViewValueColumns = options.dataViews[0].categorical.values,
grouped: DataViewValueColumnGroup[] = valueColumns.grouped(),
defaultDataPointColor: string = "green",
fillProp: DataViewObjectPropertyIdentifier = {
objectName: "objectName",
propertyName: "propertyName"
};
series.forEach((ser: powerbi.DataViewValueColumnGroup, index) => {
// create selection id for series
const seriesSelectionId = this.host.createSelectionIdBuilder()
.withSeries(options.dataViews[0].categorical.values, ser)
.createSelectionId();
// get the color from series
const defaultDataPointColor: string = this.colorPalette.getColor(ser.name.toString()).value;
let colorHelper: ColorHelper = new ColorHelper(
this.colorPalette,
fillProp,
defaultDataPointColor);
let grouping: DataViewValueColumnGroup = grouped[index];
let color = colorHelper.getColorForSeriesValue(grouping.objects, grouping.name);
// create the series elements
dataSeries.push({
value: ser.name,
selection: seriesSelectionId,
color: color
});
});
// Populate the formatting pane
this.formattingSettings.populateColorSelector(dataSeries);
}
public getFormattingModel(): powerbi.visuals.FormattingModel {
return this.formattingSettingsService.buildFormattingModel(this.formattingSettings);
}
}
Sample of data:
X | Y | Legend |
samedi 30 décembre 2023 | 14022,91642 | C |
dimanche 31 décembre 2023 | 0,551076646 | A |
dimanche 31 décembre 2023 | 10435,26002 | C |
lundi 1 janvier 2024 | 0,689471555 | A |
lundi 1 janvier 2024 | 12759,20759 | C |
mardi 2 janvier 2024 | 0,305575341 | A |
mardi 2 janvier 2024 | 10230,89312 | C |
mercredi 3 janvier 2024 | 0,587809939 | A |
mercredi 3 janvier 2024 | 11722,69859 | C |
jeudi 4 janvier 2024 | 0,964788095 | A |
jeudi 4 janvier 2024 | 13221,84671 | C |
vendredi 5 janvier 2024 | 0,721572695 | A |
vendredi 5 janvier 2024 | 11472,99755 | C |
samedi 6 janvier 2024 | 0,394463782 | A |
samedi 6 janvier 2024 | 43840,72009 | B |
samedi 6 janvier 2024 | 11982,3041 | C |
samedi 6 janvier 2024 | 515,2744629 | D |
samedi 6 janvier 2024 | 694,6464676 | E |
dimanche 7 janvier 2024 | 0,359213967 | A |
dimanche 7 janvier 2024 | 46322,50275 | B |
dimanche 7 janvier 2024 | 14065,89778 | C |
dimanche 7 janvier 2024 | 279,9718025 | D |
dimanche 7 janvier 2024 | 653,0402894 | E |
And how I fill the data fields:
Solved! Go to Solution.
Literally 3 minutes after posting the message I found the problem, and it works
fillProp: DataViewObjectPropertyIdentifier = {
objectName: "colorSelector",
propertyName: "fill"
};
The object property identifier was wrong.......
Thanks to myself lol
For those interested, here is the full code: EquinetPaul/powerbi_multiple_axis_legend_linechart: powerbi_multiple_axis_legend_linechart (github.c...
Literally 3 minutes after posting the message I found the problem, and it works
fillProp: DataViewObjectPropertyIdentifier = {
objectName: "colorSelector",
propertyName: "fill"
};
The object property identifier was wrong.......
Thanks to myself lol
For those interested, here is the full code: EquinetPaul/powerbi_multiple_axis_legend_linechart: powerbi_multiple_axis_legend_linechart (github.c...