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.
hi all,
I'm trying to create a custom slicer that looks like a table. I have gotten so far as to be able to render the table just fine however when I try and add any kind of interactivity I don't seem to be able to select any of the values:
This doesn't work:
visual.ts
export class Visual implements IVisual {
private target: HTMLElement;
private host: IVisualHost;
private selectionManager: ISelectionManager;
private selectionIdBuilder: ISelectionIdBuilder;
private table: HTMLParagraphElement;
constructor(options: VisualConstructorOptions) {
// constructor body
this.target = options.element;
this.host = options.host;
this.table = document.createElement("table");
this.target.appendChild(this.table);
this.selectionManager = this.host.createSelectionManager();
// ...
}
public update(options: VisualUpdateOptions) {
const dataView: DataView = options.dataViews[0];
const tableDataView: DataViewTable = dataView.table;
if (!tableDataView) {
return;
}
while (this.table.firstChild) {
this.table.removeChild(this.table.firstChild);
}
//draw header
const tableHeader = document.createElement("th");
tableDataView.columns.forEach((column: DataViewMetadataColumn) => {
const tableHeaderColumn = document.createElement("td");
tableHeaderColumn.innerText = column.displayName;
tableHeader.appendChild(tableHeaderColumn);
});
this.table.appendChild(tableHeader);
//draw rows
tableDataView.rows.forEach((row: DataViewTableRow, rowIndex: number) => {
const tableRow = document.createElement("tr");
row.forEach((columnValue: PrimitiveValue) => {
const cell = document.createElement("td");
cell.innerText = columnValue.toString();
tableRow.appendChild(cell);
});
this.table.appendChild(tableRow);
const selection: ISelectionId = this.host
.createSelectionIdBuilder()
.withTable(dataView.table, rowIndex)
.createSelectionId();
});
}
}
capabilities.json
{
"dataRoles": [
{
"name": "values",
"kind": "GroupingOrMeasure",
"displayName": "Values"
}
],
"dataViewMappings": [
{
"table": {
"rows": {
"select": [
{
"for": {
"in": "values"
}
}
]
}
}
}
]
}
really hope someone can troubleshoot my code as I feel like i'm banging my head against a brick wall.
EDIT: I feel like I should be adding some kind of onclick logic in here somewhere but god knows where.
Thanks
Update, with the following code I am managing to get some output in the console and I can see the other tables on the report refreshing but no filtering is taking place:
export class Visual implements IVisual {
private settings: VisualSettings;
private host: IVisualHost;
private selectionManager: ISelectionManager;
private selectionIdBuilder: ISelectionIdBuilder;
private container: d3.Selection<any, any, any, any>;
constructor(options: VisualConstructorOptions) {
console.log("Visual constructor", options);
this.host = options.host;
this.selectionManager = this.host.createSelectionManager();
/** Visual container */
this.container = d3select
.select(options.element)
.append("div")
.append("table");
}
public update(options: VisualUpdateOptions) {
this.settings = Visual.parseSettings(
options && options.dataViews && options.dataViews[0]
);
/** Clear down existing plot */
this.container.selectAll("*").remove();
/** Test 1: Data view has valid bare-minimum entries */
let dataViews = options.dataViews;
console.log("Test 1: Valid data view...");
if (
!dataViews ||
!dataViews[0] ||
!dataViews[0].table ||
!dataViews[0].table.rows ||
!dataViews[0].table.columns ||
!dataViews[0].metadata
) {
console.log("Test 1 FAILED. No data to draw table.");
return;
}
/** If we get this far, we can trust that we can work with the data! */
let table = dataViews[0].table;
/** Add table heading row and columns */
let tHead = this.container.append("tr");
table.columns.forEach((col) => {
tHead.append("th").text(col.displayName);
});
/** Now add rows and columns for each row of data */
table.rows.forEach((row, rowIndex) => {
let tRow = this.container.append("tr");
const selection: ISelectionId = this.host
.createSelectionIdBuilder()
.withTable(table, rowIndex)
.createSelectionId();
tRow.on("click", (d) => {
if (this.host.hostCapabilities.allowInteractions) {
this.selectionManager.select(selection);
console.log(selection);
}
});
row.forEach((col) => {
tRow.append("td").text(col.toString());
});
});
console.log("Table rendered!");
}
private static parseSettings(dataView: DataView): VisualSettings {
return VisualSettings.parse(dataView) as VisualSettings;
}
public enumerateObjectInstances(
options: EnumerateVisualObjectInstancesOptions
๐ VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
return VisualSettings.enumerateObjectInstances(
this.settings || VisualSettings.getDefault(),
options
);
}
}