cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
Highlighted
Frequent Visitor

Custom Visual Tooltip Data Option

Hello,

I have been working on a custom visual and would like to add a tooltip to it, although I can not get the option to appear in the "fields" area, to add data into it. Any help would be appreciated.
capabilities.json 

 

 

{    
    "objects": {},
   
    
    "dataRoles": [
        {
            "displayName": "CCFV",
            "name": "category1",
            "kind": "Grouping"
           
        }
    ],
    "tooltips": {
        "supportedTypes": {
        "default": true,
        "canvas": true
    },
        "roles": [
        "tooltips"
        ]},
    "dataViewMappings": [
        {
            "conditions": [
                {
                    "category1": {
                        "max": 1
                    }
                }
            ],
            "table": {
                "rows": {
                    "for": {
                        "in": "category1"
                    }
                }
            }
        }
    ]
}

 

 

 

Image of the editor.

 
 

img.PNG

 

visual.ts (some of it)

 

 

 

"use strict";
import "core-js/stable";
import "../style/visual.less";
import powerbi from "powerbi-visuals-api";
import IVisual = powerbi.extensibility.IVisual;
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;
import VisualObjectInstanceEnumeration = powerbi.VisualObjectInstanceEnumeration;
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
import DataView = powerbi.DataView;
import VisualTooltipDataItem = powerbi.extensibility.VisualTooltipDataItem;

import * as d3 from "d3";
import {
    createTooltipServiceWrapper,
    ITooltipEventArgs,
    ITooltipServiceWrapper,
} from "./tooltipServiceWrapper";

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



export class Visual implements IVisual {
    private element: HTMLElement;
    private isLandingPageOn: boolean;
    private LandingPageRemoved: boolean;
    private host: IVisualHost;
    private svg: Selection<SVGElement>;
    private container: Selection<SVGElement>;
    private circle: Selection<SVGElement>;
    private textValue: Selection<SVGElement>;
    private textLabel: Selection<SVGElement>;
    // Declare an array list for the line objects
    private lineOffset: Selection<SVGElement>;
    private arr = new Array();
    private arrDots = new Array();
    // Declare as array of integers to hold the segments of the circle
    private arrSegments = new Array();
    private arrOffsetSegments = new Array();
    private singleSegment: number;
    private categorys: number = 17;
    private CenterarrayOffset_ = new Array();
    private LandingPage: Selection<any>;
    virificationArray: string[];
    private tooltipServiceWrapper: ITooltipServiceWrapper;


    constructor(options: VisualConstructorOptions) {
        this.element = options.element;
        this.svg = d3.select(options.element)
            .append('svg')
            .classed('circleCard', true);
        this.host = options.host;
        this.container = this.svg.append("g")
            .classed('container', true);
            this.tooltipServiceWrapper = createTooltipServiceWrapper(this.host.tooltipService, options.element);
            this.tooltipServiceWrapper.addTooltip(this.container.selectAll('.circleCard'),
            (tooltipEvent: ITooltipEventArgs<number>) => Visual.getTooltipData(tooltipEvent.data),
            (tooltipEvent: ITooltipEventArgs<number>) => tooltipEvent.data[0]);
    }

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Highlighted
Super User I
Super User I

Re: Custom Visual Tooltip Data Option

Hi @BrentonC,

In your capabilities, you specified a role named "tooltips", but haven't supplied a dataRole for it, so update the dataRoles section of your capabilities as follows:

{
    ...
    "dataRoles": [
        {
            "displayName": "CCFV",
            "name": "category1",
            "kind": "Grouping"
        },
        {
            "displayName": "Tooltips",
            "name": "tooltips",
            "kind": "Measure"
        }
    ],
    ...
}

(the kind could be GroupingOrMeasure also, as you're using the table data view mapping; I've just gone with Measure for now)

This will then show up a place to add measure fields:

image.png

The sample bar chart has a very similar setup to this.

However if you want to make use of the measure(s) you pass in here, you'll need to update your dataViewMapping, as it will not appear in there and as such will not be accessible to the visual (note that only Dose is present):

image.png

I've modified this as follows:

{
    ...
    "dataViewMappings": [
        {
            "conditions": [
                {
                    "category1": {
                        "max": 1
                    }
                }
            ],
            "table": {
                "rows": {
                    "select": [
                        {
                            "for": {
                                "in": "category1"
                            }
                        },
                        {
                            "for": {
                                "in": "tooltips"
                            }
                        }
                    ]
                    
                }
            }
        }
    ]
    ...
}

Now, this will be accessible to the visual's data view, e.g.:

image.png

You'll then need to update your view model to include the tooltip data when you map the data view, and ensure that your getTooltipData function iterates through any additional measures you've added so that it knows what to display when the tooltip is rendered - unfortunately you haven't supplied these parts of your code for me to check, but it should be fairly straightforward for you to do if you're already mapping your category1 role into the visual's view model 🙂

Good luck!

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!




View solution in original post

4 REPLIES 4
Highlighted
Super User I
Super User I

Re: Custom Visual Tooltip Data Option

Hi @BrentonC,

In your capabilities, you specified a role named "tooltips", but haven't supplied a dataRole for it, so update the dataRoles section of your capabilities as follows:

{
    ...
    "dataRoles": [
        {
            "displayName": "CCFV",
            "name": "category1",
            "kind": "Grouping"
        },
        {
            "displayName": "Tooltips",
            "name": "tooltips",
            "kind": "Measure"
        }
    ],
    ...
}

(the kind could be GroupingOrMeasure also, as you're using the table data view mapping; I've just gone with Measure for now)

This will then show up a place to add measure fields:

image.png

The sample bar chart has a very similar setup to this.

However if you want to make use of the measure(s) you pass in here, you'll need to update your dataViewMapping, as it will not appear in there and as such will not be accessible to the visual (note that only Dose is present):

image.png

I've modified this as follows:

{
    ...
    "dataViewMappings": [
        {
            "conditions": [
                {
                    "category1": {
                        "max": 1
                    }
                }
            ],
            "table": {
                "rows": {
                    "select": [
                        {
                            "for": {
                                "in": "category1"
                            }
                        },
                        {
                            "for": {
                                "in": "tooltips"
                            }
                        }
                    ]
                    
                }
            }
        }
    ]
    ...
}

Now, this will be accessible to the visual's data view, e.g.:

image.png

You'll then need to update your view model to include the tooltip data when you map the data view, and ensure that your getTooltipData function iterates through any additional measures you've added so that it knows what to display when the tooltip is rendered - unfortunately you haven't supplied these parts of your code for me to check, but it should be fairly straightforward for you to do if you're already mapping your category1 role into the visual's view model 🙂

Good luck!

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!




View solution in original post

Highlighted
Frequent Visitor

Re: Custom Visual Tooltip Data Option

Thank you very much, I am currently working on getting it sorted as I get stuck I'll post again for sure.

 

Brenton Collins

Highlighted
Frequent Visitor

Re: Custom Visual Tooltip Data Option

I am still having issues with getting my tooltips to display, I am sure it is how I have possibly implemented them in the visual.ts file?

 

"use strict";
import "core-js/stable";
import "../style/visual.less";
import powerbi from "powerbi-visuals-api";
import { dict } from './images'; 
import IVisual = powerbi.extensibility.IVisual;
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;
import VisualObjectInstanceEnumeration = powerbi.VisualObjectInstanceEnumeration;
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
import DataView = powerbi.DataView;
import VisualTooltipDataItem = powerbi.extensibility.VisualTooltipDataItem;
import * as d3 from "d3";

import {
    TooltipEventArgs,
    TooltipEnabledDataPoint,
    createTooltipServiceWrapper,
    ITooltipServiceWrapper,
} from 'powerbi-visuals-utils-tooltiputils'


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



export class Visual implements IVisual {
    private element: HTMLElement;
    private isLandingPageOn: boolean;
    private LandingPageRemoved: boolean;
    private host: IVisualHost;
    private svg: Selection<SVGElement>;
    private container: Selection<SVGElement>;
    private circle: Selection<SVGElement>;
    // Declare an array list for the line objects
    private lineOffset: Selection<SVGElement>;
    private arr = new Array();
    private arrDots = new Array();
    // Declare as array of integers to hold the segments of the circle
    private arrSegments = new Array();
    private arrOffsetSegments = new Array();
    private singleSegment: number;
    private categorys: number = 17;
    private CenterarrayOffset_ = new Array();
    private CenterarrayOffset_bk = new Array();
    private LandingPage: Selection<any>;
    virificationArray: string[];
    private tooltipServiceWrapper: ITooltipServiceWrapper;
   



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

            
    }

    

    
    private static getTooltipData(value: any): VisualTooltipDataItem[] {
        return [{
            displayName: value.category,
            value: value.value.toString(),
            color: value.color,
            header: 'ToolTip Title'
        }];
    }
    private HandleLandingPage(options: VisualUpdateOptions) {
        console.log("landing")
        if(!options.dataViews || !options.dataViews.length) {
            if(!this.isLandingPageOn) {
                this.isLandingPageOn = true;
                const SampleLandingPage: Element = this.createSampleLandingPage();
                this.element.appendChild(SampleLandingPage);

                this.LandingPage = d3.select(SampleLandingPage);
            }

        } else {
                if(this.isLandingPageOn && !this.LandingPageRemoved){
                    this.LandingPageRemoved = true;
                    this.LandingPage.remove();
                }
            
        }
    }

    private createSampleLandingPage(): Element {
        let div = document.createElement("div");

        let header = document.createElement("h1")
        header.textContent = "Sample Bar Chart Landing Page";
        header.setAttribute("class","LandingPage");
        
        let p1 = document.createElement("a");
        p1.setAttribute("class", "LandingPageHelpLink");
        p1.textContent = "Learn more about Landing page";

        

        div.appendChild(header);
        div.appendChild(p1);

        return div;
    }
   
    public update(options: VisualUpdateOptions) {
        
        
        let dataView_: DataView = options.dataViews[0];
        // this.host.fetchMoreData();
        let width: number = options.viewport.width;
        let height: number = options.viewport.height;
        this.svg.attr("width", width);
        this.svg.attr("height", height);
        let radius: number = Math.min(width, height) / 2.4;
        let radiusDot: number = Math.min(width, height) / 250;
        let centerOffset: number;
        let cX: number;
        let cY: number;

        let cX_: number;
        let cY_: number;
        let cXOffset: number;
        let cYOffset: number;
        let counter: number;
        let counter1: number;
        let entryCounter: number;
        let ccfvfColour: string;
        this.CenterarrayOffset_ = new Array();
        this.CenterarrayOffset_bk = new Array();
        this.virificationArray = new Array();
        let colourCounter: number;
        let colourString: string;

        // To prevent from drawing everyting over and over again, remove all drawing and start again.
        this.svg.selectAll('circle').remove();
        this.svg.selectAll('image').remove();



        
        this.HandleLandingPage(options);
        entryCounter = 0
        
        for (var j = 0; j < dataView_.table.rows.length; j++) {
            if (
                this.virificationArray.indexOf(dataView_.table.rows[j].toString().split(",")[2]) > -1){

                }
                else{
                    this.virificationArray.push(String(dataView_.table.rows[j].toString().split(",")[2]))
                }

            }


        this.circle = this.container.append("circle")
            .classed('circle', true);




        // Create the lines for the categorys to split the kelly wheel into 17 sections

        for (let i = 0; i < this.categorys; i++) {
            this.arr.push(this.container.append("line").classed("line_" + i, true));
        }

        // Get the single segments of the kelly wheel in deg of 360
        this.singleSegment = 360 / this.arr.length;
        for (var i = 0; i < this.arr.length; i++) {
            this.arrSegments.push(this.singleSegment * i)
        }

        for (var a = 0; a < this.virificationArray.length; a++) {
 
            this.arrDots[a] = new Array();
            entryCounter = 0
           
            for (var j = 0; j < dataView_.table.rows.length; j++) {
                if (
                    dataView_.table.rows[j].toString().split(",")[2] == this.virificationArray[a]) {
                    entryCounter = entryCounter + 1
                }
            }

            for (var i = 0; i < entryCounter; i++) {
                this.arrDots[a].push(this.container.append("circle").classed("circle__" + a + "_" + i, true));
            }
        }

        /*
        *  Get the edge of the circle
        */
        this.circle
            .style("stroke", "black")
            .style("stroke-width", 2)
            .attr("r", radius)
            .attr("cx", width / 2)
            .attr("cy", height / 2)
            .style("fill", "#ffe500");


        counter = 0
        counter1 = 0
        
        for (var i = 0; i < 17; i++) {
            cX = (width / 2) + radius * Math.cos(this.arrSegments[i] * Math.PI / 180);
            cY = (height / 2) + radius * Math.sin(this.arrSegments[i] * Math.PI / 180);

            cX_ = width / 2 - radius  * Math.cos(this.arrSegments[i] );
            cY_ = height / 2 - radius * Math.sin(this.arrSegments[i] );

            centerOffset = 40;
            // outer offset
            cXOffset = (width / 2) + radius * Math.cos((this.arrSegments[i]) * Math.PI / 180);
            cYOffset = (height / 2) + radius * Math.sin(this.arrSegments[i] * Math.PI / 180);

            this.arr[i]
                .attr("x1", '50%')
                .attr("y1", '50%')
                .attr("x2", cX)
                .attr("y2", cY)
                .attr("stroke-width", 3)
                .attr("stroke", "black");
            centerOffset = 0



            // left right | up down | in out
            this.CenterarrayOffset_ =
                // First loop
                [[23, 4, .06], //1
                [20, 13, .06], //2
                [15, 19, .06], //3
                [4, 22, .06], //4
                [-3, 23, .06],//5
                [-11, 20, .06],//6
                [-18, 16, .06],//7
                [-22, 6, .06],//8
                [-22, -1, .06],//9
                [-20, -9, .06],//10
                [-14, -16, .06],//11
                [-9, -20, .06],//12
                [-1, -20, .06],//13
                [7, -20, .06],//14
                [13, -17, .06],//15
                [18, -11, .06],//16
                [22, -3, .06]]//17

            for (var z = 0; z < this.arrDots[counter].length; z++) {
                if(z >=138){
                    // Max 138 per FV section
                    continue
                }

                colourCounter = 0
            

                for (var j = 0; j < dataView_.table.rows.length; j++) {
                  
                //    console.log(this.virificationArray[a])
                    if (
                        dataView_.table.rows[j].toString().split(",")[2] == this.virificationArray[i]) {
                            
                        colourCounter = colourCounter + 1
                    }

                    if (colourCounter == z) {
                        colourString = dataView_.table.rows[j].toString().split(",")[1]
                    }
                }

                if (colourString == "Yes") {
                    ccfvfColour = "green"
                }
                else {
                    ccfvfColour = "red"
                }

                this.arrDots[i][z]
                    .style("fill", ccfvfColour)
                    .style("stroke", ccfvfColour)
                    .style("stroke-width", 2)
                    .attr("r", radiusDot)
                    .attr("cx", (this.CenterarrayOffset_[counter1][2] + centerOffset) * (cXOffset - (width / 2) + this.CenterarrayOffset_[counter1][0]) + (width / 2) + this.CenterarrayOffset_[counter1][0])
                    .attr("cy", (this.CenterarrayOffset_[counter1][2] + centerOffset) * (cYOffset - (height / 2) + this.CenterarrayOffset_[counter1][1]) + (height / 2) + this.CenterarrayOffset_[counter1][1])
                    
                    
                    ;
                centerOffset = (radius / 800000) + centerOffset + 0.025
               if(z == 0){
                this.CenterarrayOffset_bk = [
                    [15,    10, .48], //1
                    [0,    20, .48], //2
                    [-15,    22, .48], //3
                    [-30,     23, .48], //4
                    [-40,    12, .48],//5
                    [-44,   3, .48],//6
                    [-48,   -12, .48],//7
                    [-47,   -27, .48],//8
                    [-45,   -37, .48],//9    6
                    [-35, -45, .48],//10
                    [-20, -53, .48],//11
                    [-10, -50, .48],//12
                    [6, -45, .48],//13
                    [15, -38, .48],//14
                    [24, -28, .48],//15
                    [36, -18, .48],//16
                    [40, -8, .48]]
            
        
                this.container.append("svg:image")
                .attr("xlink:href",dict[this.virificationArray[i]])
                .attr("x", (.9 + centerOffset) * (cXOffset - (width / 2) + this.CenterarrayOffset_bk[counter1][0]) + (width / 2) + this.CenterarrayOffset_bk[counter1][0])
                .attr("y", (.9 + centerOffset) * (cYOffset - (height / 2) + this.CenterarrayOffset_bk[counter1][1]) + (height / 2) + this.CenterarrayOffset_bk[counter1][1]).
                attr("width", 50)
                .attr("height", 50);;
             

               }
                if (z == 29) {

                    centerOffset = 0
                    this.CenterarrayOffset_ = [
                        [28, 12, .08], //1
                        [20, 22, .08], //2
                        [13, 29, .08], //3
                        [0, 31, .08], //4
                        [-10, 28, .08],//5
                        [-19, 22, .08],//6
                        [-27, 15, .08],//7
                        [-30, 2, .08],//8
                        [-28, -8, .08],//9
                        [-23, -18, .08],//10   2
                        [-15, -25, .08],//11
                        [-7, -28, .08],//12
                        [5, -27, .08],//13
                        [14, -24, .08],//14
                        [22, -19, .08],//15
                        [28, -9, .08],//16
                        [30, 2, .08]]
                }

                if (z == 58) {
                    //-  left right +|- up down +| in out
                    centerOffset = 0
                    this.CenterarrayOffset_ = [
                        [28,    19, .18], //1
                        [19,    30, .18], //2
                        [5,    32, .18], //3
                        [-7,     31, .18], //4
                        [-17,    28, .18],//5
                        [-27,   21, .18],//6
                        [-33,   9, .18],//7   3
                        [-34,   -3, .18],//8
                        [-28,   -15, .18],//9
                        [-25, -27, .18],//10
                        [-14, -33, .18],//11
                        [1, -30, .18],//12
                        [11, -27, .18],//13
                        [22, -24, .18],//14
                        [28, -15, .18],//15
                        [32, -3, .18],//16
                        [30, 9, .18]]
                }

                if (z == 82) {
                    //-  left right +|- up down +| in out
                    centerOffset = 0
                    this.CenterarrayOffset_ = [
                        [28,    26, .26], //1
                        [17,    37, .26], //2
                        [-2,    36, .26], //3
                        [-14,     32, .26], //4
                        [-25,    28, .26],//5
                        [-35,   20, .26],//6
                        [-39,   5, .26],//7
                        [-39,   -9, .26],//8    4
                        [-28,   -22, .26],//9
                        [-23, -35, .26],//10
                        [-10, -39, .26],//11
                        [7, -34, .26],//12
                        [18, -27, .26],//13
                        [28, -18, .26],//14
                        [34, -10, .26],//15
                        [36, 3, .26],//16
                        [30, 16, .26]]
                }


                if (z == 102) {
                    //-  left right +|- up down +| in out
                    centerOffset = 0
                    this.CenterarrayOffset_ = [
                        [19,    33, .39], //1
                        [6,    40, .39], //2
                        [-9,    40, .39], //3
                        [-22,     31, .39], //4
                        [-33,    22, .39],//5
                        [-38,   9, .39],//6
                        [-40,   -5, .39],//7
                        [-32,   -20, .39],//8
                        [-25,   -30, .39],//9
                        [-12, -39, .39],//10
                        [1, -39, .39],//11
                        [16, -33, .39],//12    5
                        [26, -25, .39],//13
                        [34, -16, .39],//14
                        [35, 1, .39],//15
                        [36, 12, .39],//16
                        [30, 24, .39]]
                }

                if (z == 120) {
                    //-  left right +|- up down +| in out
                    centerOffset = 0
                    this.CenterarrayOffset_ = [
                        [17,    40, .54], //1
                        [0,    45, .54], //2
                        [-15,    43, .54], //3
                        [-30,     31, .54], //4
                        [-40,    21, .54],//5
                        [-44,   6, .54],//6
                        [-43,   -12, .54],//7
                        [-33,   -27, .54],//8
                        [-25,   -37, .54],//9    6
                        [-10, -45, .54],//10
                        [9, -41, .54],//11
                        [24, -33, .54],//12
                        [33, -25, .54],//13
                        [40, -12, .54],//14
                        [41, 5, .54],//15
                        [36, 20, .54],//16
                        [30, 31, .54]]
                }


                
                if (z == 132) {
                   //-  left right +|- up down +| in out
                    centerOffset = 0
                    this.CenterarrayOffset_ = [
                        [15,    47, .70], //1
                        [-4,    50, .70], //2
                        [-23,    43, .63], //3
                        [-37,     31, .63], //4
                        [-47,    21, .63],//5
                        [-50,   3, .63],//6
                        [-43,   -21, .63],//7    7
                        [-37,   -32, .63],//8
                        [-21,   -44, .63],//9
                        [-4, -50, .63],//10
                        [15, -45, .63],//11
                        [31, -34, .63],//12
                        [40, -24, .63],//13
                        [46, -8, .63],//14
                        [47, 8, .63],//15
                        [35, 28, .63],//16
                        [30, 38, .63]]
                }

                if (z == 152) {
                    //-  left right +|- up down +| in out
                    centerOffset = 0
                    this.CenterarrayOffset_ = [
                        [11,    52, .80], //1
                        [-11,    53, .80], //2
                        [-29,    45, .80], //3
                        [-43,     31, .80], //4
                        [-53,    16, .80],//5
                        [-53,   -5, .80],//6
                        [-47,   -25, .80],//7
                        [-35,   -40, .80],//8
                        [-21,   -50, .80],//9
                        [0, -55, .80],//10    8
                        [18, -50, .80],//11
                        [36, -37, .80],//12
                        [47, -24, .80],//13
                        [52, -6, .80],//14
                        [50, 14, .80],//15
                        [40, 31, .80],//16
                        [30, 44, .80]]
                }

                if (z == 140) {
                    // left right | up down | in out
                    centerOffset = 0
                    // Get the remainder of CCFV and add a number to the end of the column

                }


            }
            this.svg.selectAll("line").raise()
            counter = counter + 1
            counter1 = counter1 + 1

   
        }

        this.tooltipServiceWrapper.addTooltip(this.svg.selectAll('circle'), 
       (tooltipEvent: TooltipEventArgs<number>) => 
 Visual.getTooltipData(tooltipEvent.data),
        (tooltipEvent: TooltipEventArgs<number>) => null);
        
        this.arrDots = []
        this.arr = []
    }
}
Highlighted
Frequent Visitor

Re: Custom Visual Tooltip Data Option

Update:

I ended up getting it sorted, I added each object as they were made in a loop as such.

 

                let dot = this.arrDots[i][z]
                    .style("fill", ccfvfColour)
                    .style("stroke", ccfvfColour)
                    .style("stroke-width", 2)
                    .attr("r", radiusDot)
                    .attr("cx", (this.CenterarrayOffset_[counter1][2] + centerOffset) * (cXOffset - (width / 2) + this.CenterarrayOffset_[counter1][0]) + (width / 2) + this.CenterarrayOffset_[counter1][0])
                    .attr("cy", (this.CenterarrayOffset_[counter1][2] + centerOffset) * (cYOffset - (height / 2) + this.CenterarrayOffset_[counter1][1]) + (height / 2) + this.CenterarrayOffset_[counter1][1])
                
                    this.tooltipServiceWrapper.addTooltip(dot,
                        (tooltipEvent: TooltipEventArgs<number>) => this.getTooltipData(tooltipEvent.data),
                        (tooltipEvent: TooltipEventArgs<number>) => null
                        // Get the remainder of CCFV and add a number to the end of the column
                        )

 Thank You 

Helpful resources

Announcements
May 2020 Community Highlights

May 2020 Community Highlights

It’s time for another PBI Community recap!

Community Blog

Community Blog

Visit our Community Blog for articles, guides, and information created by fellow community members.

Using the Community

Using the Community

Need help with the Power BI Community? Our 'Using the Community' support articles are a great place to start.

Galleries

Galleries

Looking for inspiration on how to present your data? Need instructional videos? Check out our Galleries!