Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Earn the coveted Fabric Analytics Engineer certification. 100% off your exam for a limited time only!

Reply
Anonymous
Not applicable

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 this little bit and want to show a percentage based on Actual Value and Target Value and fill the circle according to the percentage i.e. if the percentage is 85% then fill 85% circle with a different color. I have managed to do this using the below sort of code in the Update method of the visual lifecycle.

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

        gradient.append("stop").attr("offset", + fillPercent + "%").style("stop-color", "red");

        gradient.append("stop").attr("offset", fillPercent + "%").style("stop-color", "white");

        this.circle
            .style("fill", function () {
                return "url(#gradient)";
            })
            .style("fill-opacity", 1)
            .style("stroke", "black")
            .style("stroke-width", this.visualSettings.gauge.circleThickness)
            .attr("r", radius)
            .attr("cx", width / 2)
            .attr("cy", height / 2);

The problem is that the gradient fill is not getting refreshed based on the percentage I need to press the reload visual button. (See below)

captured.gifI have attached my visual.ts file for the reference. 

Please let me know what's wrong here? 

Thank you in advance.

 

Please click here to open visual.ts 

1 ACCEPTED SOLUTION
dm-p
Super User
Super User

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:

dm-p_0-1595188573671.png

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:

defs.gif

And if we expand this, it looks as follows:

dm-p_1-1595188940755.png

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:

defs_remove.gif

Regards,

Daniel





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

Proud to be a Super User!


My course: Introduction to Developing Power BI Visuals


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




View solution in original post

3 REPLIES 3
dm-p
Super User
Super User

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:

dm-p_0-1595188573671.png

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:

defs.gif

And if we expand this, it looks as follows:

dm-p_1-1595188940755.png

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:

defs_remove.gif

Regards,

Daniel





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

Proud to be a Super User!


My course: Introduction to Developing Power BI Visuals


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




Anonymous
Not applicable

Hello @dm-p,

Thank you so much for your detailed explanation. It resolved my issue.

Thank you once again.

No worries! Glad it's working for you 🙂





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

Proud to be a Super User!


My course: Introduction to Developing Power BI Visuals


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




Helpful resources

Announcements
April AMA free

Microsoft Fabric AMA Livestream

Join us Tuesday, April 09, 9:00 – 10:00 AM PST for a live, expert-led Q&A session on all things Microsoft Fabric!

March Fabric Community Update

Fabric Community Update - March 2024

Find out what's new and trending in the Fabric Community.

Top Solution Authors
Top Kudoed Authors