Forum Discussion
Power BI Custom Visual: Customize series mechanism example
As per this: https://powerbi.microsoft.com/en-us/blog/introducing-the-new-format-pane-preview/
Is there an example on how to get the customize series mechanism.
In my formatting pane I am getting the options succeffully in the dropdown and in the formattingSettings object. But they are not updating.
Return formattingSettings:
{
"columnWidth": {
"container": {
"displayName": "Apply settings to",
"containerItems": [
{
"width": {
"name": "width",
"displayName": "Column Width",
"description": "Set the width of this column (pixels)",
"value": 120,
"options": {
"maxValue": {
"type": 1,
"value": 1000
},
"minValue": {
"type": 0,
"value": 20
}
},
"type": "NumUpDown"
},
"name": "row_0",
"displayName": "work_year",
"slices": [
{
"name": "width",
"displayName": "Column Width",
"description": "Set the width of this column (pixels)",
"value": 120,
"options": {
"maxValue": {
"type": 1,
"value": 1000
},
"minValue": {
"type": 0,
"value": 20
}
},
"type": "NumUpDown"
}
]
},
{
"width": {
"name": "width",
"displayName": "Column Width",
"description": "Set the width of this column (pixels)",
"value": 120,
"options": {
"maxValue": {
"type": 1,
"value": 1000
},
"minValue": {
"type": 0,
"value": 20
}
},
"type": "NumUpDown"
},
"name": "row_1",
"displayName": "job_title",
"slices": [
{
"name": "width",
"displayName": "Column Width",
"description": "Set the width of this column (pixels)",
"value": 120,
"options": {
"maxValue": {
"type": 1,
"value": 1000
},
"minValue": {
"type": 0,
"value": 20
}
},
"type": "NumUpDown"
}
]
},
{
"width": {
"name": "width",
"displayName": "Column Width",
"description": "Set the width of this column (pixels)",
"value": 120,
"options": {
"maxValue": {
"type": 1,
"value": 1000
},
"minValue": {
"type": 0,
"value": 20
}
},
"type": "NumUpDown"
},
"name": "value_0",
"displayName": "Sum of salary_in_usd",
"slices": [
{
"name": "width",
"displayName": "Column Width",
"description": "Set the width of this column (pixels)",
"value": 120,
"options": {
"maxValue": {
"type": 1,
"value": 1000
},
"minValue": {
"type": 0,
"value": 20
}
},
"type": "NumUpDown"
}
]
},
{
"width": {
"name": "width",
"displayName": "Column Width",
"description": "Set the width of this column (pixels)",
"value": 120,
"options": {
"maxValue": {
"type": 1,
"value": 1000
},
"minValue": {
"type": 0,
"value": 20
}
},
"type": "NumUpDown"
},
"name": "value_1",
"displayName": "RR",
"slices": [
{
"name": "width",
"displayName": "Column Width",
"description": "Set the width of this column (pixels)",
"value": 120,
"options": {
"maxValue": {
"type": 1,
"value": 1000
},
"minValue": {
"type": 0,
"value": 20
}
},
"type": "NumUpDown"
}
]
}
]
},
"name": "columnWidth",
"displayName": "Column Width"
}
}
This is what I code have implemented:
- capabilties.json:
object: {
"columnWidth": {
"displayName": "Column Widths",
"properties": {
"width": {
"displayName": "Column Width",
"description": "Set Column Width.",
"type": {
"numeric": true
}
}
}
}
}- Settings.ts:
import powerbi from "powerbi-visuals-api";
import { formattingSettings } from "powerbi-visuals-utils-formattingmodel";
// Column Width Card for per-column dropdown
export class ColumnWidthCardItem extends formattingSettings.SimpleCard {
public width: formattingSettings.NumUpDown = new formattingSettings.NumUpDown({
name: "width",
displayName: "Column Width",
description: "Set the width of this column (pixels)",
value: 120,
options: {
maxValue: {
type: powerbi.visuals.ValidatorType.Max,
value: 1000
},
minValue: {
type: powerbi.visuals.ValidatorType.Min,
value: 20
}
}
});
constructor(name?: string, displayName?: string, widthValue?: number) {
super();
this.name = name || "";
this.displayName = displayName || name || "";
if (typeof widthValue === "number") {
this.width.value = widthValue;
}
this.slices = [this.width];
}
}
class ColumnWidthCardSetting extends formattingSettings.SimpleCard {
public container: formattingSettings.Container = {
displayName: "Apply settings to",
containerItems:[new ColumnWidthCardItem()]
};
constructor() {
super();
this.name = "columnWidth";
this.displayName = "Column Width";
}
}
// Main Settings Model
/**
* Main settings model for the Power BI visual formatting pane. Contains all formatting cards and option groups.
*/
export class VisualSettingsModel {
columnWidth: ColumnWidthCardSetting;
cards: Array<formattingSettings.SimpleCard | formattingSettings.CompositeCard>;
constructor() {
this.columnWidth = new ColumnWidthCardSetting();
this.cards = [
this.columnWidth
];
}
}-visual.ts:
this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(VisualSettingsModel, dataView);
// Dynamically create per-column width cards for the formatting pane using formatted columns
if (dataView && dataView.matrix) {
const formatted = formatMatrixForFGGrid(dataView.matrix);
console.log("Formatted: ", formatted)
const formattedColumns = formatted.columns || [];
const fieldWidthCardItems = formattedColumns.map((col: any) => {
// Use col.index for name and col.title for displayName
let widthValue = 120;
if (this.formattingSettings?.columnWidth?.container?.containerItems) {
const match = this.formattingSettings.columnWidth.container.containerItems.find((item: any) => item.name === col.index);
if (match && match.width) {
widthValue = match.width.value;
}
}
return new ColumnWidthCardItem(col.index, col.title, widthValue);
});
console.log("fieldWidthCardItems: ", fieldWidthCardItems);
// Set the containerItems array on the formattingSettings model
if (this.formattingSettings?.columnWidth?.container) {
console.log("Updating columnWidth with formatted columns.");
this.formattingSettings.columnWidth.container.containerItems = [];
this.formattingSettings.columnWidth.container.containerItems.push(...fieldWidthCardItems);
console.log("formattingSettings: ", this.formattingSettings);
}
}
1 Reply
- BeaBFSuper User
Settings.ts:
import powerbi from "powerbi-visuals-api";
import { formattingSettings, formattingSettingsCard, formattingSettingsTypes } from "powerbi-visuals-utils-formattingmodel";// --- Dynamic Column Width Item ---
export class ColumnWidthCardItem extends formattingSettings.SimpleCard {
public width: formattingSettings.NumUpDown;constructor(name: string, displayName: string, widthValue: number) {
super();
this.name = name; // dynamic key
this.displayName = displayName; // what shows in the formatting panethis.width = new formattingSettings.NumUpDown({
name: "width",
displayName: "Column Width",
value: widthValue,
options: {
minValue: { type: formattingSettingsTypes.ValidatorType.Min, value: 20 },
maxValue: { type: formattingSettingsTypes.ValidatorType.Max, value: 1000 },
},
});// Important: binds this property to the card
this.slices = [this.width];
}
}// --- Container Card ---
export class ColumnWidthCardSetting extends formattingSettings.SimpleCard {
public container: formattingSettings.Container;constructor() {
super();
this.name = "columnWidth";
this.displayName = "Column Width";// Initialize empty container for dynamic items
this.container = {
displayName: "Apply settings to",
containerItems: []
};
}
}// --- Main Visual Settings Model ---
export class VisualSettingsModel {
columnWidth: ColumnWidthCardSetting;
cards: Array<formattingSettings.SimpleCard | formattingSettings.CompositeCard>;constructor() {
this.columnWidth = new ColumnWidthCardSetting();
this.cards = [this.columnWidth];
}
}Visual.ts:
// Populate formatting settings
this.formattingSettings = this.formattingSettingsService.populateFormattingSettingsModel(
VisualSettingsModel,
dataView
);// Only proceed if dataView has matrix data
if (dataView && dataView.matrix) {
const formattedColumns = formatMatrixForFGGrid(dataView.matrix).columns || [];// Generate dynamic container items per column
const containerItems = formattedColumns.map((col: any) => {
// Default width value (can come from previous saved settings)
let widthValue = 120;// Check if a value already exists in formattingSettings
const match = this.formattingSettings.columnWidth.container.containerItems.find(
(item: any) => item.name === col.index
);
if (match && match.width) {
widthValue = match.width.value;
}return new ColumnWidthCardItem(col.index, col.title, widthValue);
});// Assign dynamically generated items to the container
this.formattingSettings.columnWidth.container.containerItems = containerItems;
}// --- OPTIONAL: log to debug ---
console.log("Dynamic ColumnWidth Settings:", this.formattingSettings);-
Each ColumnWidthCardItem has a slices array pointing to its width property.
-
Do not replace the entire formattingSettings object after the visual has been initialized — just update containerItems.
-
populateFormattingSettingsModel must run before rendering the formatting pane, so Power BI knows about the slices.
-
The name of the card item (col.index) is used to track which column the setting belongs to.
BBF
💡 Did I answer your question? Mark my post as a solution!
👍 Kudos are appreciated
🔥 Proud to be a Super User!
-