Forum Discussion
mdmason
4 years agoRegular Visitor
Table like slicer
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
1 Reply
- mdmasonRegular Visitor
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 ); } }