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
mdmason
New Contributor II

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 1
mdmason
New Contributor II

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
    );
  }
}

Helpful resources

Announcements
Users online (25)