Search code examples
javascripthtmlcsschartschart.js

How do I update the chart to reflect local storage values?


I'm using chart.js to make a tracker program. The chart here takes in user input values and produces a chart. I want it users to be able to save the values in localStorage, which I can successfully do. The problem lies in the retrieval of chart values and producing the chart. I've tried using the chart.update(); and chart.render(); functions but they do not create the chart. How do I fix this?

HTML

```<div class="form-container" style="float: left; margin-left: 80px; margin-top: 13px; text-align: center; padding-bottom: 530px; margin-bottom: 20px; padding-top: 10px;">
            <form>

                <!---Monday--->
                <div class="sleep">
                    <p style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">Monday</p>
                    <input type="integer" name="monday" id="monday" placeholder="Monday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>

                <!---Tuesday--->
                <div class="sleep">
                    <p style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">Tuesday</p>
                    <input type="integer" name="tuesday" id="tuesday" placeholder="Tuesday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>

                <!---Wednesday--->
                <div class="sleep">
                    <p style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">Wednesday</p>
                    <input type="integer" name="wednesday" id="wednesday" placeholder="Wednesday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>

                <!---Thursday--->
                <div class="sleep">
                    <p style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">Thursday</p>
                    <input type="integer" name="thursday" id="thursday" placeholder="Thursday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>

                <!---Friday--->
                <div class="sleep">
                    <p style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">Friday</p>
                    <input type="integer" name="friday" id="friday" placeholder="Friday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>

                <!---Saturday--->
                <div class="sleep">
                    <p style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">Saturday</p>
                    <input type="integer" name="saturday" id="saturday" placeholder="Saturday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>

                <!---Sunday--->
                <div class="sleep">
                        <p style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">Sunday</p>
                    <input type="integer" name="sunday" id="sunday" placeholder="Sunday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>
            </form>

            <!---Save and clear buttons for local storage--->
            <div>
            <button class="save-btn" id="save-btn">Save</button>

           <button class="clear-btn" id="clear-btn">Clear</button>
            </div>

        </div>```

JAVASCRIPT

```<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<div class="chart-container" style=" float: right; margin-right: 100px; position: relative; height: 60vh; width: 60vw; margin-top: 100px">
    
<canvas id="myChart" width="100px" height="100px"></canvas>

<script>


//Chart setup and configuration
let chartData =[]
const ctx = document.getElementById('myChart');
const myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
        datasets: [{
            label: 'Hours of sleep',
            data: chartData,

            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)',
                'rgba(222, 184, 135, 0.2)'
            ],
            borderColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)',
                'rgba(222, 184, 135, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            y: {
            beginAtZero: true
          }
        }
    }
});


//Removing general data
function removeData(chart) {
    chart.data.datasets.forEach((dataset) => {
        dataset.data.pop();
    });
    chart.update();
}

//Adding user data in
function addData(chart, data) {
    
    chart.data.datasets.forEach((dataset) => {
               
        dataset.data = [...data]
    });
    chart.update();
}


//Calling input values to update chart
function updateChart(event){
    
    event.preventDefault()
    monValue = Number(document.getElementById('monday').value);
    tuesValue = Number(document.getElementById('tuesday').value);
    wedValue = Number(document.getElementById('wednesday').value);
    thursValue = Number(document.getElementById('thursday').value);
    friValue = Number(document.getElementById('friday').value);
    satValue = Number(document.getElementById('saturday').value);
    sunValue = Number(document.getElementById('sunday').value);
    
    chartData = [
        monValue,
        tuesValue,
        wedValue,
        thursValue,
        friValue,
        satValue,
        sunValue
]
    removeData(myChart)
    addData(myChart, chartData)
    
}

//Updating chart with values
var sleepBtn = document.querySelectorAll('.sleep-btn');
sleepBtn.forEach(btn => {
    btn.addEventListener('click', updateChart, false)
})


//Local storage functions
const saveButton = document.querySelector('.save-btn');
const clearButton = document.querySelector('.clear-btn');

const dataPoints = JSON.parse(window.localStorage.getItem("sdps"));

function storageValues(){
    myChart.update(myChart, sdps);
    chart.render();
}



const saveToLocalStorage = () =>{
    window.localStorage.setItem('sdps', JSON.stringify(chartData));
} 

function clearStorage(){
    localStorage.clear();
};

saveButton.addEventListener('click', saveToLocalStorage);
clearButton.addEventListener('click', clearStorage);


</script>
</div>```
   

Solution

  • I'd approach this by setting the initial state of the UI based on the localStorage values.

    let chartData = loadFromLocalStorage();
    setUIData(chartData);
    

    Then I'd have all the enter buttons and the Save button do essentially the same thing: get the current data from the UI, save it to localStorage, and then update the chart.

    function updateChart(event) {
        if (event) event.preventDefault();
        chartData = getUIData();
        saveToLocalStorage(chartData);
        addData(myChart, chartData);
    }
    

    The full code looks like the following. See working example at https://jsbin.com/bujomeliho/3/edit?html,output (I would have used the embedded snippets here on SO but localStorage is disallowed.)

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    
        <div class="form-container"
            style="float: left; margin-left: 80px; margin-top: 13px; text-align: center; padding-bottom: 530px; margin-bottom: 20px; padding-top: 10px;">
            <form>
    
                <!-- Monday -->
                <div class="sleep">
                    <p
                        style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">
                        Monday</p>
                    <input type="number" name="monday" id="monday" placeholder="Monday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>
    
                <!-- Tuesday -->
                <div class="sleep">
                    <p
                        style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">
                        Tuesday</p>
                    <input type="number" name="tuesday" id="tuesday" placeholder="Tuesday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>
    
                <!-- Wednesday -->
                <div class="sleep">
                    <p
                        style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">
                        Wednesday</p>
                    <input type="number" name="wednesday" id="wednesday" placeholder="Wednesday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>
    
                <!-- Thursday -->
                <div class="sleep">
                    <p
                        style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">
                        Thursday</p>
                    <input type="number" name="thursday" id="thursday" placeholder="Thursday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>
    
                <!-- Friday -->
                <div class="sleep">
                    <p
                        style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">
                        Friday</p>
                    <input type="number" name="friday" id="friday" placeholder="Friday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>
    
                <!-- Saturday -->
                <div class="sleep">
                    <p
                        style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">
                        Saturday</p>
                    <input type="number" name="saturday" id="saturday" placeholder="Saturday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>
    
                <!-- Sunday -->
                <div class="sleep">
                    <p
                        style="color: #55725d; font-size: 20px; text-align: left; font-style: bold; margin-bottom: 4px; text-align: center; margin-top: 18px;">
                        Sunday</p>
                    <input type="number" name="sunday" id="sunday" placeholder="Sunday" value="">
                    <button class="sleep-btn" style="margin-left: 78px;">Enter</button>
                </div>
            </form>
    
            <!-- Save and clear buttons for local storage -->
            <div>
                <button class="save-btn" id="save-btn">Save</button>
    
                <button class="clear-btn" id="clear-btn">Clear</button>
            </div>
    
        </div>
        <div class="chart-container"
            style=" float: right; margin-right: 100px; position: relative; height: 60vh; width: 60vw; margin-top: 100px">
            <canvas id="myChart" width="100px" height="100px"></canvas>
        </div>
    
        <script>
            //Chart setup and configuration
            let chartData = loadFromLocalStorage();
            setUIData(chartData);
    
            const ctx = document.getElementById('myChart');
            const myChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
                    datasets: [{
                        label: 'Hours of sleep',
                        data: chartData,
                        backgroundColor: [
                            'rgba(255, 99, 132, 0.2)',
                            'rgba(54, 162, 235, 0.2)',
                            'rgba(255, 206, 86, 0.2)',
                            'rgba(75, 192, 192, 0.2)',
                            'rgba(153, 102, 255, 0.2)',
                            'rgba(255, 159, 64, 0.2)',
                            'rgba(222, 184, 135, 0.2)'
                        ],
                        borderColor: [
                            'rgba(255, 99, 132, 1)',
                            'rgba(54, 162, 235, 1)',
                            'rgba(255, 206, 86, 1)',
                            'rgba(75, 192, 192, 1)',
                            'rgba(153, 102, 255, 1)',
                            'rgba(255, 159, 64, 1)',
                            'rgba(222, 184, 135, 1)'
                        ],
                        borderWidth: 1
                    }]
                },
                options: {
                    scales: {
                        y: {
                            beginAtZero: true
                        }
                    }
                }
            });
    
            //Adding user data in
            function addData(chart, data) {
                chart.data.datasets.forEach((dataset) => {
                    dataset.data = [...data]
                });
                chart.update();
            }
    
            //Calling input values to update chart
            function updateChart(event) {
                if (event) event.preventDefault();
                chartData = getUIData();
                saveToLocalStorage(chartData);
                addData(myChart, chartData);
            }
    
            //Updating chart with values
            document.querySelectorAll('.sleep-btn').forEach(btn => {
                btn.addEventListener('click', updateChart);
            });
    
            function setUIData(data) {
                document.querySelectorAll('.sleep input').forEach((el, i) => el.value = data[i] || '');
            }
    
            function getUIData() {
                return Array.from(document.querySelectorAll('.sleep input'))
                    .map(el => Number(el.value));
            }
    
            //Local storage functions
            function loadFromLocalStorage() {
                return JSON.parse(localStorage.getItem('sdps') || '[]');
            }
    
            function saveToLocalStorage(chartData) {
                localStorage.setItem('sdps', JSON.stringify(chartData));
            }
    
            function clearStorage() {
                localStorage.clear();
                setUIData(['','','','','','','']);
                updateChart();
            };
    
            document.querySelector('.save-btn').addEventListener('click', updateChart);
            document.querySelector('.clear-btn').addEventListener('click', clearStorage);
        </script>
    </body>
    </html>