Home > Blockchain >  Chart js multiple pie chart on one page
Chart js multiple pie chart on one page

Time:04-05

Iam building my portfolio website and i build a simple stocktracker. I added some charts from Chart.js, but somehow only one gets rendered when I excecute the code.

I managed to assign all the divs and data dynamically by making the variables dynamic. I did this by adding the portfolio id in the for loop. I can't figure out why its not working. Appreciate any help.

{% extends 'base.html' %}
{% block page_content %}
{% if user.is_authenticated %}
<body>
<div >
    <div >
        <div >
            <h2>
                Welcome to the stocktracker
            </h2>
            <p>I build this stocktracker app to learn database operations. To get current stock data, I linked this to
                the free API from Polygon.io. It's only possible to do 5 API calls per minute. You will see an error
                message whenever the api calls are exceeded.
                <br><br>Current features are:
            <ol>
                <li>Basic CRUD database operation</li>
                <li>Adding portfolio's linked to user</li>
                <li>Only show portfolio's linked to user</li>
                <li>Show general KPI's in portfolio overview</li>
                <li>KPI's calculated based on positions in portfolio</li>
                <li>Adding position to portfolio</li>
                <li>API connection with Polygon.io to get live stock data</li>
                <li>Chart.js integration for visual representation of portfolio metrics</li>
            </ol>
            </p>
        </div>
    </div>
    <div >
        <div >
            <h2>Select your portfolio</h2>
        </div>
        <div >
            <!-- Button trigger modal -->
            <button type="button"  data-bs-toggle="modal" data-bs-target="#addPortfolioModal">
                Add new portfolio
            </button>

            <!-- Modal -->

            <div  id="addPortfolioModal" tabindex="-1" role="dialog"
                 aria-labelledby="addPortfolioModalLabel"
                 aria-hidden="true">
                <div  role="document">
                    <div >
                        <div >
                            <h5  id="addPortfolioLabel">Modal title</h5>
                            <button type="button"  data-bs-dismiss="modal" aria-label="Close">
                                <span aria-hidden="true">&times;</span>
                            </button>
                        </div>
                        <div >
                            <form name="portfolio_form" method="post">
                                {% csrf_token %}
                                <p>
                                    {{ portfolio_form }}
                                </p>
                                <div >
                                    <button type="button"  data-bs-dismiss="modal">Close
                                    </button>
                                    <input type="submit" value="Submit"/>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div>
            {% for portfolio in portfolios %}
            <div >
                <div >
                    <a  href="{% url 'portfolio_detail' portfolio.pk%}">Go to {{ portfolio }}</a>
                </div>
            </div>
            {% if portfolio.total_positions > 0 %}
            <div>
                {% load static %}
                <div  style="width: 50%;">
                    <canvas id="pie-chart{{ portfolio.pk }}"></canvas>

                    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js"></script>
                    <script>
                    var randomNum_{{ portfolio.pk }} = () => Math.floor(Math.random() * (235 - 52   1)   52);
                    function rgbToHex(r, g, b) {
                        return "#"   ((1 << 24)   (r << 16)   (g << 8)   b).toString(16).slice(1);
                    }
                    countPositions = {{ portfolio.total_positions|safe }};

                    var barColors_{{ portfolio.pk }} = [];
                    for (let i = 0; i < countPositions; i  ) {
                        randomGeneratedColor = rgbToHex(randomNum_{{ portfolio.pk }}(), randomNum_{{ portfolio.pk }}(), randomNum_{{ portfolio.pk }}());
                        while (barColors_{{ portfolio.pk }}.includes(randomGeneratedColor)) {
                            randomGeneratedColor = rgbToHex(randomNum(), randomNum(), randomNum());
                        }
                        barColors_{{ portfolio.pk }}.push(randomGeneratedColor);
                    }
                    var config_{{ portfolio.pk }} = {
                        type: 'pie',
                        data: {
                            datasets: [{
                                data: {{ portfolio.data_for_chart_array|safe }},
                                backgroundColor: barColors_{{ portfolio.pk }},
                                label: 'Stock ticker'
                            }],
                            labels: {{ portfolio.labels_array|safe }}
                        },
                        options: {
                            responsive: true
                        }
                    };

                    window.onload = function() {
                        var ctx = document.getElementById('pie-chart{{ portfolio.pk }}').getContext('2d');
                        window.myPie = new Chart(ctx_{{ portfolio.pk }}, config_{{ portfolio.pk }});
                    };

                    </script>
                </div>
            </div>
            {% endif %}
            <div >
                <div >
                    <b>Total amount invested:</b> {{ portfolio.total_amount_invested }}
                    <br><b>Positions:</b> {{ portfolio.total_positions }}
                    <br><b>Profit:</b> {{ portfolio.total_profit }}
                    <br><b>Profit in %:</b> {{ portfolio.total_profit_percentage }} %
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg OMhuP IlRH9sENBO0LRn5q 8nbTov4 1p"
            crossorigin="anonymous"></script>
</div>
</body>
{% endif %}
{% endblock %}

enter image description here

Somehow only the last chart gets rendered instead of all three.

CodePudding user response:

You have a loop there, and in each iteration of the loop, you're using window.onload = function() {…};

Basically, you're overwriting the onload function at each iteration of the loop, so only the last overwrite survives.

What you want is to add load event listeners on the window instead of continually overwriting one single listener.

To achieve this, I would recommend replacing this:

window.onload = function () {…}

with this:

window.addEventListener('load', function() {…})`

See addEventListener

Another way of seeing that window.onload = function () {…} is problematic is the following snippet:

window.onload = function () { alert('one') };
window.onload = function () { alert('two') };

Q: What do you expect to happen on page load here?

A: Similarly to your case, only the second function (alerting "two") will be called.

  • Related