Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
6 years ago
Solved

Power BI Custom Visuals - Gradient Fill id not getting refreshed

Hello everyone, I have just started learning to create Power BI custom visuals and I have created my first custom visual i.e. Circle Card by referring the Microsoft tutorial. Now, I want to modify ...
  • dm-p's avatar
    6 years ago

    Hi Anonymous,

    As we only have your visual.ts to go on, I can't reproduce fully locally to confirm, the first line in your posted snippet is the suspect:

    var gradient = this.container.append("defs").append("linearGradient").attr("id", "gradient")
                .attr("x1", "0%").attr("x2", "0%").attr("y1", "100%").attr("y2", "0%");

    How this is currently written, will append a defs element to your container element each time the update method runs, rather than replacing it. This is because your container property (and it's children) is persisted across the lifecycle of the visual.

    So, when you start your visual and the update method runs for the first time the gradient is applied as you expect (akin to  your scenario of refreshing the visual to see it in your post). When you update your visual, the original will still be there in the g element represented by this.container.

    So, here's what it might look like on the first run:

    Now, if I update the visual in a similar way to you, e.g. changing a slicer value, this happens to your DOM when the update method runs:

    And if we expand this, it looks as follows:

    Hopefully the above should help illustrate that there are 5 defs now attached, and SVG will just be using the first one that was originally added as it's not been cleared down.

    There are more elegant ways to solve this, but for minimal changes to your code, add the following line prior to the var gradient... declaration, e.g.:

    ...
    
    this.container.select('defs').remove();
    var gradient = this.container.append("defs").append("linearGradient").attr("id", "gradient")
                .attr("x1", "0%").attr("x2", "0%").attr("y1", "100%").attr("y2", "0%");
    
    ...

    This checks for the presence of a defs element and removes it prior to adding the new one, and hopefully this is close to what you're after:

    Regards,

    Daniel