tigrr / circle-progress

Responsive, accessible, animated, stylable with CSS circular progress bar available as plain (vanilla) JS and jQuery plugin.
https://tigrr.github.io/circle-progress
MIT License
164 stars 43 forks source link

Failed to set the "textFormat" property when using with Vue and custom function textFormat #25

Closed nirpan closed 10 months ago

nirpan commented 10 months ago

I am using the latest version of circle-progress (^1.0.0-beta.0) on a Vue 3 project built with vite and its working as expected but I cannot seem to get it to work when proving a function for the textFormat prop as per the documentation.

This is how I am using it which is a direct copy of the example:

:text-format="
      function (value, max) {
        return value + ' dots';
      }
    "

I have created a StackBlitz with two progress circle - one using the value textFormat which works fine and the other with the function textFormat which does not work.

The reason I am trying to do this is I need to have a custom text within the circle and normally I would do it like this in Vue but this is not possible with this component:

<circle-progress>
<div class="custom-text">78</div>
</circle-progress>

Would be great to know what I am doing wrong here, thanks!

tigrr commented 10 months ago

Since you are using textFormat as a property and not as an attribute (of course you can't use the attribute form to pass a function), you have to use the property form textFormat, not the attribute form text-format. Please, refer to the properties / attributes table for the property and attribute names. Also, I think you have a mix up of textFormat and text-format in Donut.vue and App.vue files, which you should fix too.

nirpan commented 10 months ago

I didn't realise textFormat and text-format would be different as in Vue it does not matter if you use text-format or textFormat for passing a property and it works the same way. Changing it to the following sort of fixed it.

<circle-progress
    ref="circleProgress"
    :value="progress"
    :max="max"
    :start-angle="startAngle"
    :animation-duration="3000"
    :anti-clockwise="reverse"
    :textFormat="textFormat"
  ></circle-progress>

But looks like passing a html like <h2>H2</h2> won't work unless I am misunderstanding this:

is expected to return a string of HTML to insert in the center of the progress circle

If you check the updated StackBlitz it is outputting as follows which I guess is not really valid:

<text class="text" part="text" x="50" y="50" dy="0.4em"><h2>H2</h2></text>

I even tried this but doesn't seem to work either. It just outputs the value but I cannot see the h2 element.

'<foreignObject><h2>H2</h2></foreignObject>';

Is there no way to do this?

tigrr commented 10 months ago

You ate right, it should rather be a string of SVG code. I will update the docs. And h2 is of course not an SVG tag. You can use tspan or just style circle-progress::part(value) as you need.

nirpan commented 10 months ago

I tried doing it that way but for my use case, I could only achieve it as follows (with additional custom styling) since there are no <slot> usage:

<div class="circle">
    <div class="circle-body">
      <div class="donut-chart-value">
        <span>A long text value</span>
      </div>
    </div>
    <Donut ref="donut" :progress="40" class="donut-one" />
  </div>

My use case was replacing this Vue package: https://github.com/vrajroham/vue-circle-progress/blob/master/src/index.vue