'How to loop over Chart.js with Django list view

I am using a Django List View, and I am trying to iterate through multiple objects and display percentage values in a Chart.JS gauge.

However, although I am iterating the names of the gauge id's by using a for loop counter, I am only ever getting the first iteration of the chart.js object rendering on my screen. My initial thoughts are that similar to how I am dynamically creating new canvas ids for the chart.js objects, I should be doing a similar thing for the variable I am trying to pass into the chart object e.g. reduction overall, but I am not having any luck. Your feedback is welcome.

Views.py

class PerformanceDetailView(ListView):
template_name = 'performance_detail.html'
model = Performance
context_object_name = 'performance'

def get_queryset(self, **kwargs):
    code = self.kwargs.get('code')
    return Performance.objects.filter(code=code)

Performance_detail.html

  <section class="projects pt-4 col-lg-12">
    {% for item in performance %}
    <div class="container-fluid pt-2 col-lg-12">
      <!-- Project--><div class="project" >
      <div class="row bg-white has-shadow" style="height: 14rem">
        <div class="left-col col-lg-2 d-flex align-items-center justify-content-between">
          <div class="project-title d-flex align-items-center">
              <div class="has-shadow"><img src="{% static 'img/avatar-2.jpg' %}" alt="..." class="img-fluid"></div>
          </div>
        </div>
        <div class="right-col col-lg-2 align-items-center vertical-center">
          <div class="text">
            <h3 class="h2 pt-2">{{item.brand}} {{item.style}}</h3>
            <p class="text-muted">{{item.package_type| capfirst}} package, round {{item.testing_round}}</p>
            <p class="text-muted">Item size: {{item.size}}</p>
          </div>
        </div>

        <div class="right-col col-lg-8 align-items-center vertical-center">
          <div class="row mt-5">
            <div class="col-md-3">
              <div class="gauge-container">
                <canvas id="gauge1-{{ forloop.counter }}" class="gauge-canvas"></canvas><span id="gauge1Value-{{ forloop.counter }}" class="gauge-label"></span>
              </div>
            </div>
        </div>
        </div>
     </div>
   </div>
  </div>
{{ item.reduction_overall|json_script:"reduction_overall" }}
{{ for_loop_counter|json_script:"for_loop_counter" }}
{% endfor %}
</section>
{% endblock content %}

Block JS within package_detail.html


<!-- Gauge.js-->
<script src="{% static 'vendor/gaugeJS/gauge.min.js' %}"></script>
<script> 
$(function () {
    var reduction_overall = JSON.parse(document.getElementById('reduction_overall').textContent);
    var for_loop_counter = JSON.parse(document.getElementById('for_loop_counter').textContent);

    // Gauges
    var gauge1 = document.getElementById('gauge1-'+for_loop_counter);

    opts.colorStop = "#864DD9";
    var gaugeObject1 = new Donut(gauge1).setOptions(opts); 

    gaugeObject1.maxValue = 100; // set max gauge value
    gaugeObject1.setMinValue(0); // set min value
    gaugeObject1.set(reduction_overall); // set actual value
    gaugeObject1.setTextField(document.getElementById("gauge1Value-" + for_loop_counter));

});
</script>
{% endblock js %}


Solution 1:[1]

This was solved by including the JavaScript in the main block content and dynamically naming the gauge elements themselves.

var func_name = "container-{{forloop.counter}}"; 
func_name = new Donut(gauge1).setOptions(opts);

I posted a full example to a similar problem here Chart JS and Django loop

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tim