Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
3 years ago

Costum Visual Tooltip don't works

Hello,
I'm working on a custom visual and I have very basic a square that when you move on it, it displays a tooltip. (the tooltip should display a report page).

i Used the addTooltip Method like the description on learn.microsoft.com.

 

visual.ts

 

 

"use strict";

import "core-js/stable";
import "./../style/visual.less";
import powerbi from "powerbi-visuals-api";
import powerbiVisualsApi from "powerbi-visuals-api";
import VisualEnumerationInstanceKinds = powerbiVisualsApi.VisualEnumerationInstanceKinds;
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import DataView = powerbi.DataView;
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
import * as d3 from "d3";
import {
    select as d3Select
} from "d3-selection";
import {
    scaleLinear,
    scaleBand
} from "d3-scale";



//tooltip imports
import VisualTooltipDataItem = powerbi.extensibility.VisualTooltipDataItem;
import { createTooltipServiceWrapper, ITooltipServiceWrapper, TooltipEventArgs } from "powerbi-visuals-utils-tooltiputils";
import { csvParseRows, Numeric, schemeSet3, treemapSquarify } from "d3";

import DataViewMetadataColumn = powerbi.DataViewMetadataColumn;
import DataViewTable = powerbi.DataViewTable;
import DataViewTableRow = powerbi.DataViewTableRow;
import PrimitiveValue = powerbi.PrimitiveValue;


import ISelectionId = powerbi.visuals.ISelectionId;

type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;


export class Visual implements IVisual {
    private host: IVisualHost;
    private svg: Selection<SVGElement>;
    private container: Selection<SVGElement>;
    private rect: Selection<SVGElement>;
    private textValue: Selection<SVGElement>;
    private tooltipServiceWrapper: ITooltipServiceWrapper;
    private table: HTMLParagraphElement;

    private selection: d3.Selection<d3.BaseType, any, d3.BaseType, any>;


    constructor(options: VisualConstructorOptions) {
        this.svg = d3.select(options.element)
            .append('svg')
            .classed('excel2', true);
        this.host = options.host;
        this.container = this.svg.append("g")
            .classed('container', true);
        this.tooltipServiceWrapper = createTooltipServiceWrapper(this.host.tooltipService, options.element);
        this.rect = this.container.append("rect")

            .classed('rect', true);
        this.textValue = this.container.append("text")
            .classed("textValue", true);

        this.table = document.createElement("table");
        this.target.appendChild(this.table);
    }




    public update(options: VisualUpdateOptions) {

        let dataView: DataView = options.dataViews[0];
        let tableDataView: DataViewTable = dataView.table;

        let width: number = options.viewport.width;
        let height: number = options.viewport.height;
        let index = dataView.table.rows.length - 1;

        this.svg
            .attr("width", width)
            .attr("height", height);


        //TEXT hinzufügen und Ausrichtung
        let fontSizeValue: number = Math.min(width, height) / 8;
        if (width < height) {
            this.container.selectAll("text")
                .attr("transform", "rotate(-90)")
            this.textValue
                .text(<string>dataView.table.rows[0][1])     
                .attr("x", -(height / 2))
                .attr("y", width / 2)
                .attr("text-anchor", "middle")
                .style("font-size", fontSizeValue + "px");
         
        } else {
            this.textValue
                .text(<string>dataView.table.rows[0][1])      
                .attr("x", width / 2)
                .attr("y", height / 2)
                .attr("text-anchor", "middle")
                .style("font-size", fontSizeValue + "px")
                .attr("transform", "rotate(0)");
        }
        //rechteck für statusanzeige
        this.rect
            .style("fill-opacity", 0.5)
            .style("stroke", "black")
            .style("stroke-width", 5)
            .attr("width", width)
            .attr("height", height);
//[....]

        this.tooltipServiceWrapper.addTooltip(
            this.svg.selectAll('rect'),
            (tooltipEvent: TooltipEventArgs<number>) => Visual.getTooltipData(tooltipEvent.data),
            (tooltipEvent: TooltipEventArgs<number>) => null,
            true);


    }


    public static getTooltipData(value: any): VisualTooltipDataItem[] {
        return [{
            displayName: value,
            value: value,
            color: value,
            header: 'tooltip title'
        }];
    }


}

 

 

 And ich declare the getTooltipData method also (with examples just to try if its work)

 

capabilities.json

 

 

    "tooltips": {
        "supportedTypes": {
            "default": true,
            "canvas": true
        },
        "roles": [
            "Tooltips"
        ],
        "supportEnhancedTooltips": true
    }

 

 

 

 Can someone possibly help me and tell me what I have to consider?

 

Thank you

 

3 Replies

  • dm-p's avatar
    dm-p
    Super User

    Hi Anonymous,

    The issue is in the third parameter of your addTooltip method, i.e.:

            this.tooltipServiceWrapper.addTooltip(
                this.svg.selectAll('rect'),
                (tooltipEvent: TooltipEventArgs<number>) => Visual.getTooltipData(tooltipEvent.data),
                (tooltipEvent: TooltipEventArgs<number>) => null, <--- THIS PART
                true);

    This expects an ISelectionId and you are passing null to it, which means that Power BI has no context for the tooltip columns and measures needed to resolve it on your behalf.

    You will need to create a selection for the desired data point that the element represents, so that Power BI can resolve it for you and display the correct canvas tooltip.

    Provided that the desired column or measure is included in your selection, and the report page tooltip contains one of these then it should then resolve as you expect.

    If you want to see an example of this, the MS sampleBarChart has the addTooltip call here, and the selection ID creation as part of mapping the dataset here.

    Good luck!

    Daniel

    • Anonymous's avatar
      Anonymous
      Not applicable

      Hello Daniel,
      thank you for your quick reply. My data structure is a table data view. on the page: https://learn.microsoft.com/de-de/power-bi/developer/visuals/selection-api . Is described how this works however I don't know what "rowDiv" does?!

          const dataView = options.dataViews[0];
          dataView.table.rows.forEach((row: DataViewTableRow, rowIndex: number) => {
              this.target.appendChild(rowDiv);  <-- here
              const selection: ISelectionId = this.host.createSelectionIdBuilder()
                  .withTable(dataView.table, rowIndex)
                  .createSelectionId();
          }

      I am new in creating custom Visials please forgive me 😄 

       

       

    • hobbykitjr's avatar
      hobbykitjr
      New Member

      Hey Daniel, Whats messed up w/ OPs code is actually how MS has it in their documentation:

      https://learn.microsoft.com/en-us/power-bi/developer/visuals/add-tooltips#call-the-addtooltip-method

       

      this.tooltipServiceWrapper.addTooltip(this.barContainer.selectAll('.bar'),
                  (tooltipEvent: TooltipEventArgs<number>) => BarChart.getTooltipData(tooltipEvent.data),
                  (tooltipEvent: TooltipEventArgs<number>) => null);

       

       

      I suspect what MS meant to enter was 

       

      this.tooltipServiceWrapper.addTooltip(this.barContainer.selectAll('.bar'),
                  (tooltipEvent: TooltipEventArgs<number>) => BarChart.getTooltipData(tooltipEvent.data),
                  null);

       

       

      Which would would work but only to display static information... The documenation and examples is all over the place and broken for this.