Skip to main content
cancel
Showing results forย 
Search instead forย 
Did you mean:ย 

Calling all Data Engineers! Fabric Data Engineer (Exam DP-700) live sessions are back! Starting October 16th. Sign up.

Reply
a-smiggle
New Contributor

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 1
BeaBF
Valued Contributor III

@a-smiggle 

 

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


๐Ÿ’ก Did I answer your question? Mark my post as a solution!

๐Ÿ‘ Kudos are appreciated

๐Ÿ”ฅ Proud to be a Super User!

Community News image 1920X1080.png

 

Helpful resources

Announcements
Users online (2,086)