5

I want to create div's dynamically based on the number of elements present in an array. The div's contain the html element created by ProgressBar.js.

This the Vue.js code

import ProgressBar from 'progressbar.js'
var bar;

export default {
    data() {
        return {
            fitness: ['Run', 'Cycle'],
            val: 0.65
        }
    },

    mounted(){
        this.showProgressBar(this.val);
    },


    created: function() {

    },

    methods:{
         showProgressBar: function(val){
            new ProgressBar.Circle('#container',{
                trailColor: 'gainsboro',
                trailWidth: 20,
                color: 'teal',
                strokeWidth: 20
            }).animate(val); 
         }
    }
}
<div class="content" v-for="fitness in fitness">
  <span>{{ fitness }}</span>
  <div id="container"></div>
</div>

Since an id is associated with only one div, I am not able to execute a new ProgressBar.Circle object that would create another div. Is there a way to dynamically create a new div with different a id inside the v-for every time the new ProgressBar.circle is executed? Can somenone please help me out here?

1
  • 1
    What you would typically do is create a component that wraps ProgressBar and render that. Commented Aug 16, 2017 at 18:22

2 Answers 2

5

Here is a re-usable component that wraps progressbar.js.

<template>
  <div class="container"><div ref="bar"></div></div>
</template>
<script>
  import ProgressBar from "progressbar.js"

  export default {
    props:["options", "val"],
    mounted(){
      new ProgressBar.Circle(this.$refs.bar, this.options).animate(this.val)
    } 
  }
</script>
<style>
  .container{
    width:100px; 
    height: 100px
  }
</style>

Here is how it's used in a template:

<div v-for="fit in fitness" class="fitness">
  <div>{{fit.name}}</div>
  <progress-bar :val="fit.val" :options="options"></progress-bar>
</div>

Working Example.

Sign up to request clarification or add additional context in comments.

7 Comments

@APJ No problem :) There are some improvements that could be made. Monitor changes to val for example so that the progress could dynamically change. Allow the dimensions (size in px) to be set, etc. But this is a decent start.
There is a small issue, though. I don't see a division or a line between the div's
@apj which divs? Each fitness?
Yes. between each fitness
@APJ Thats just a style issue, and not really with the component. I added a 10px margin to the example. You can see it in the styles of the app.vue.
|
3

One solution could be give unique ids to each container div and create progress bars for each of them.

Try the code below -

import ProgressBar from 'progressbar.js'
var bar;

export default {
  data() {
    return {
      fitness: ['Dietary Intake', 'Exercise'],
      val: [0.65, 9]
    }
  },

  mounted() {
    this.showProgressBar();
  },


  created: function() {

  },

  methods: {
    showProgressBar: function() {
      this.fitness.forEach((f, i) => {
        new ProgressBar.Circle('#container-' + i, {
          trailColor: 'gainsboro',
          trailWidth: 20,
          color: 'teal',
          strokeWidth: 20
        }).animate(this.val[i]);
      });

    }
  }
}
<div class="content" v-for="(f, index) in fitness">
  <span>{{ f }}</span>
  <div v-bind:id="`container-${index}`"></div>
</div>

Update - val can be an array. And its values can be referenced from the within the showProgressBar function.

I am assuming the length of fitness and val arrays are the same.

Update 2 - Explanation.

So basically there are 2 main issues here that have to addressed.

1. Generating multiple container divs

We need to generate multiple container divs as there are going to be multiple ProgressBars. But we need to distinguish between them so we create a unique id for each of them. That is what the following code does.

<div class="content" v-for="(f, index) in fitness">
  <span>{{ f }}</span>
  <div v-bind:id="`container-${index}`"></div>
</div>

Since index numbers are unique. Adding them to "container" generated unique ids. See List Rendering

2. Generate multiple ProgressBars when component mounts.

This is simpler we simple create new ProgressBar for each "fitness" value.

this.fitness.forEach((f, i) => {
  new ProgressBar.Circle('#container-' + i, {
    trailColor: 'gainsboro',
    trailWidth: 20,
    color: 'teal',
    strokeWidth: 20
  }).animate(this.val[i]);

Refer - Array forEach

4 Comments

Thanks. But, how do I pass the val dynamically everytime the div gets executed? Like if I had val : [0.65, 1.25, 9].
you could just have an array of vals, and you could reference them in showProgressBar.
Yes. done. Also, can you please explain how the code works? I would like to learn. I am quite new to Vue.js

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.