Join us at FabCon Atlanta from March 16 - 20, 2026, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.
Register now!Calling all Data Engineers! Fabric Data Engineer (Exam DP-700) live sessions are back! Starting October 16th. Sign up.
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);
}
}
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 pane
this.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