Forum Discussion
Custom visual tooltip service not working
I'm writing a custom visual with some KPIs and a bar chart. I have created the bar chart by following the below article.
https://tsmatz.wordpress.com/2016/09/27/power-bi-custom-visuals-programming/
The visual is working fine. Now I want a display a tooltip when mouse hovered on the bar chart. I followed the below documentation (couldn't understand most of it) and implemented the same.
https://github.com/Microsoft/PowerBI-visuals/blob/master/Visual/Tooltips.md
My visual doesn't show anything. When I cross-checked the culprit was this line in the constructor.
When I commented this line, my visual works fine. What I'm I doing wrong? How to get the tooltips working?
Please help asap!
Thank you for sharing. We're going to look into the issue.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
v-viig Thanks for sharing the solution. Below were the changes done in my code.
this.tooltipServiceWrapper.addTooltip(this.svg.selectAll('.bar'),(tooltipEvent: TooltipEventArgs<BarData>) => Visual.getTooltipData(tooltipEvent.data),(tooltipEvent: TooltipEventArgs<BarData>) => null);
private static getTooltipData(data: BarData): VisualTooltipDataItem[] {
return [{
displayName: data.Date,
value: `${data.Indicator}`,
}];
}
11 Replies
- v-viigCommunity Champion
Did you implement createTooltipServiceWrapper?
Can you share the whole source code of your custom visual?
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals
- satishrHelper III
Copied tooltipServiceWrapper.ts file from https://github.com/Microsoft/PowerBI-visuals-sampleBarChart and pasted in my src folder.
Added "src/tooltipServiceWrapper.ts" to tsconfig.json files part.
Below is my visual.ts. Please let me know if I'm missing anything.
Now, the visual doesn't show anything. If I comment the first line in the constructor the bar graph shows without tooltips.module powerbi.extensibility.visual { "use strict"; import ValueFormatter = powerbi.extensibility.utils.formatting.valueFormatter; export interface BarData { Indicator: number; Category: string; } export class Visual implements IVisual { private svg: d3.Selection<SVGElement>; private g: d3.Selection<SVGElement>; private host: IVisualHost; private tooltipServiceWrapper: ITooltipServiceWrapper; private bColorPos: string; private bColorNeg: string; constructor(options: VisualConstructorOptions) { this.tooltipServiceWrapper = createTooltipServiceWrapper(this.host.tooltipService, options.element); this.svg = d3.select(options.element).append('svg'); this.g = this.svg.append('g'); this.bColorPos = "#32CD32"; this.bColorNeg = "#FD625E"; } public update(options: VisualUpdateOptions) { this.setObjectProperties(options); this.generateBarChart(options); } public setObjectProperties(options: VisualUpdateOptions) { if (options.dataViews[0].metadata.objects) { if (options.dataViews[0].metadata.objects["bar"] && options.dataViews[0].metadata.objects["bar"]["bColorPos"]) {this.bColorPos = options.dataViews[0].metadata.objects["bar"]["bColorPos"]["solid"]["color"].toString();} if (options.dataViews[0].metadata.objects["bar"] && options.dataViews[0].metadata.objects["bar"]["bColorNeg"]) {this.bColorNeg = options.dataViews[0].metadata.objects["bar"]["bColorNeg"]["solid"]["color"].toString();} } } public generateBarChart(options: VisualUpdateOptions){ var _this = this; var barColor1 = this.bColorPos; var barColor2 = this.bColorNeg; _this.svg.attr({ height: options.viewport.height, width: options.viewport.width }); var gHeight = options.viewport.height * 0.5; var gWidth = options.viewport.width ; _this.g.attr({ height: gHeight, width: gWidth }); _this.g.attr('transform','translate(0,0)'); // convert data format var data = Visual.dataForBarGraph(options); // setup d3 scale var xScale = d3.scale.ordinal() .domain(data.map(function (d) { return d.Category; })) .rangeRoundBands([0, gWidth], 0.1); var yMax = d3.max(data, function (d) { return d.Indicator }); var yScale = d3.scale.linear() .domain([0, yMax]) .range([gHeight, 0]) // remove exsisting axis and bar _this.svg.selectAll('.bar').remove(); // draw bar var shapes = _this.g .append('g') .selectAll('.bar') .data(data); shapes.enter() .append('rect') .attr('class', function (d) { return d.Indicator < 0 ? "bar negative" : "bar positive"; }) .attr('fill', function (d) { return d.Indicator < 0 ? barColor2 : barColor1; }) .attr('x', function (d) { return xScale(d.Category); }) .attr('width', xScale.rangeBand()) .attr('y', function (d) { return d.Indicator < 0 ? yScale(0) : yScale(d.Indicator); }) .attr('height', function (d) { return d.Indicator < 0 ? yScale(d.Indicator) - yScale(0) : gHeight - yScale(d.Indicator); }) this.tooltipServiceWrapper.addTooltip(this.svg.selectAll('.bar'), (tooltipEvent: TooltipEventArgs<number>) => Visual.getTooltipData(tooltipEvent.data), (tooltipEvent: TooltipEventArgs<number>) => null); shapes.exit().remove(); } public static dataForBarGraph(options: VisualUpdateOptions): BarData[] { var resultData: BarData[] = []; var rows = options.dataViews[0].table.rows; for (var i = 0;i < rows.length;i++) { var row = rows[i]; resultData.push({ Indicator: +row[0].toString(), Category: row[2].toString() }); } return resultData; } public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration { let objectName = options.objectName; let objectEnumeration: VisualObjectInstance[] = []; switch (objectName) { case 'bar': objectEnumeration.push({ objectName: objectName, properties: { bColorPos: this.bColorPos, bColorNeg: this.bColorNeg, }, selector: null }); break; }; return objectEnumeration; } private static getTooltipData(value: any): VisualTooltipDataItem[] { return [{ displayName: value.category, value: value.value.toString(), color: value.color }]; } public destroy(): void { //TODO: Perform any cleanup tasks here } } }- v-viigCommunity Champion
this.host is undefined in the constructor. Please take host object form options at contrcutor.
Ignat Vilesov,
Software Engineer
Microsoft Power BI Custom Visuals