Charts Initialization Issue using GridStack.js & Charts.js in PHP Yii2

127 Views Asked by At

I am trying to make a dashboard in PHP yii2 project using gridstack.js and chart.js

I have given a dropdown button where the user can select the KPI chart, the selected chart gets added to the grid of gridstack.js

Problem 1: If i load the charts in incremental order: Chart 1, Chart 2, Chart 3.... and so on it get's initialized in the grid without any problem. But if i select any random chart other than the chart 1 the selected chart does not get initialized.

Problem 2: Once the grid is saved, and then loaded. So if a user wants to add one more chart to the loaded grid so that he/she may update the saved grid => A new grid is created and the loaded grid vanishes.

I am 100% sure that the problem lies in the initializeChart function. And I have tried multiple things as per the resources available online but all in vain. Some of the things i have tried are:

  1. separate the initializeChart function and chart's data and to call chart data as per the user request.
  2. I have tried to use if else statements, if elseif statements and switch statements in the initializeChart function as well

But once i modify the initializeChart function, not even a single graph gets initialized. Whereas currently they are being initialized if called in incremental order.

Below is my complete code. Please help me out in fixing the problem.

Note: I have removed few graphs data to fit the limit. All graphs data are fictitious so you can copy paste any graph data and rename it to make it work.

P.S. Any help would be highly appreciated. Thanks in advance!


<?php

/** @var yii\web\View $this */

use yii\helpers\Html;

$this->title = 'About';
$this->params['breadcrumbs'][] = $this->title;
?>
<?php
$this->registerJsFile('https://cdn.jsdelivr.net/npm/chart.js', ['position' => \yii\web\View::POS_HEAD]);
?>

<!DOCTYPE html>
<html>

<head>

    <style type="text/css">
        .grid-stack {
            background: lightslategray;
        }

        .grid-stack-item-content {
            text-align: start;
            background-color: whitesmoke;
        }

        .grid-stack-item {
            min-height: 80px;
        }

        .grid-stack-item-removing {
            opacity: 0.8;
            filter: blur(5px);
        }

        #trash {
            background: rgba(255, 0, 0, 0.6);
        }

     
    </style>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">


    <script type="module" src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"></script>
    <script nomodule="" src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack.min.js"
        integrity="sha512-V4/oQa+3p3Nu7kSK1DLdTvD3+03q/2MMvszJ84JLroRjUvZ82YcplQ7IJX6XiZXuJtESbUBL+gcGF03F5D+n5Q=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/dd-base-impl.min.js"
        integrity="sha512-mhZn+o/RSWCNMh6NpFW4pTDzGcqwhL2xH2RdRHOQ5dnj5HDrlPwMuHZdAwB8ZOXZcIhR6IgzXUh4DuG13PsPDg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/dd-draggable.min.js"
        integrity="sha512-a41HfVO6a33kYNNTiVMwzCOgNo0RLhmEhKm0K1EiBludHHsjXbyUXcs3jMQpLs1mipx3yR2e5aInebX0e3dNTg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/dd-droppable.min.js"
        integrity="sha512-0MXd7MHHvnDPlwTnGHxxPSk83jr3n04ozR/9D7WpKf7fr7kva7/Syfd8Obki4tIx0NOSzkn8wvlR6CrAFPWRWQ=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/dd-element.min.js"
        integrity="sha512-zvWjOI2JNrhq7K/mfZu0zg6wHRd7iWDF5g7cc4QC6ZbGpIXlc6C1bFoDcj9KqQkU2G56x81qq+NQKRVNbDc2LQ=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/dd-gridstack.min.js"
        integrity="sha512-rfwTdhmMbnmMNjp+H46Bfm5bEQOPMDJ8cWKIzP3JyLWCxo9nlrsjqyfGMe3sAocY7JFm3rH13VH2ZJtPj61Gjw=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/dd-manager.min.js"
        integrity="sha512-7c2iOKYLmwWFiZ0bdYJ1p8EvDwJFbFBvKTfVgLBCpPlLiXlITMumR/9aymNLEGqfVNzQjg+hJKcATL3PvZhY9A=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/dd-resizable-handle.min.js"
        integrity="sha512-47UKx0R1s2WYC47SoxCO+OC256GghdA8sRVGTOzb4ehV1SnEBFS1+lujNb3bWW5abegJ+yVGKs8V93iqv4E3hg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/dd-resizable.min.js"
        integrity="sha512-qfVbqxjrtBLIYkAVlicMMiLKO9Jl27UpU4YARHuKvKDUzrar97zKlkdpcXNgBtNaXsZ0NQMSwz0vg9Lxs4ezyA=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/dd-touch.min.js"
        integrity="sha512-qjqVUYIO1ooxh8d3mhry2CoKxkqekgZU778GJNfD1bZxUlvUrpl/YMjKvzwwhmWPef/eSvbfHJ0Rj3HAZfJarg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack-all.min.js"
        integrity="sha512-gq8R31XSsOjp58K9qre4n5inuaUuAkz36qmdVx9Y1VpGtzmx06JlnVGLEDMISZH1Kh/M2X4Iip40WPD94kQW2w=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack-engine.min.js"
        integrity="sha512-wHYVJ9RRSpsxBgtDstxRb35Dlh6zXCxwzU3fTLyD81ltBG/ZJi9x82A9heWjcX6ykZ+ga8EkCFkKymUYhpwT0g=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack-extra.min.css"
        integrity="sha512-287EQpO1sItRDNvuCUARDlhpQs3qLRCMaidpOKp5BFu6EgcX3XxB92jmTvdXWW57Q9ImHcYqIHKx12EATT3sPA=="
        crossorigin="anonymous" referrerpolicy="no-referrer" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/gridstack.min.css"
        integrity="sha512-RQiZSqRhRB5xAwqOKws34d14fPNaxoy59RNAUl2KXtT+5XfmspdKoNo1C2hR1bunSSLd4wNOz1bYcZjvuzN0hg=="
        crossorigin="anonymous" referrerpolicy="no-referrer" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/types.min.js"
        integrity="sha512-Or1RaobYJlngoRviBZqCv5kO0PbmajRZ+1uPrcWYWkNQPTU/wgg+IQPtIliaPiVh7/qhJv+qK9oZPsaTsMEiUg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/10.0.1/utils.min.js"
        integrity="sha512-C+//7CsrykaET+j6aiHKpZ12zf+POQPB8t6SQ2Q0HOvadZ0vBuBfTT27/w06JhqJfXdntps6dbaLhKQfMPZ+vg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>

</head>

<body>
    <div class="site-about mb-0 pb-0">
       
        <h1>GridStackJs</h1>

        <div class="col-12">

            <div class="btn-group">
                <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown"
                    aria-haspopup="true" aria-expanded="false">
                    <ion-icon name="add-circle"></ion-icon>Add KPI
                </button>
                <div class="dropdown-menu">
                    <a class="dropdown-item add-chart" href="#" data-chart="occupancyChart">Occupancy</a>
                    <a class="dropdown-item add-chart" href="#" data-chart="roomsChart">Rooms</a>
                    <a class="dropdown-item add-chart" href="#" data-chart="contractsChart">Contracts</a>
                    <a class="dropdown-item add-chart" href="#" data-chart="employeeChart">Employee</a>
                    <a class="dropdown-item add-chart" href="#" data-chart="revenueChart">Revenue</a>
                    <a class="dropdown-item add-chart" href="#" data-chart="invoicesChart">Invoices</a>
                    <a class="dropdown-item add-chart" href="#" data-chart="paymentChart">Payment</a>
                    <a class="dropdown-item add-chart" href="#" data-chart="visitorsChart">Visitors</a>
                    <a class="dropdown-item add-chart" href="#" data-chart="maintenanceChart">Maintenance</a>
                </div>
            </div>
            <a onclick="saveFullGrid()" class="btn btn-secondary" href="#">Save Full Grid</a>
            <a onclick="loadFullGrid()" class="btn btn-secondary" href="#">Load Full Grid</a>
            <a onclick="clearGrid()" class="btn btn-secondary" href="#">Reset</a>
            <a id="trash" class="btn btn-danger" href="#"><ion-icon name="trash"></ion-icon>Drag here to remove!</a>
            <br /><br />
            <div id="gridCont" class="grid-stack"></div>
            <hr />
            <textarea id="saved-data" style="width: 100%" cols="100" rows="20" readonly="readonly"></textarea>
        </div>
     
        <script type="text/javascript">



            let grid = GridStack.init({
                cellHeight: 70,
                acceptWidgets: true,
                removable: '#trash', // drag-out delete class
                float: true,
            })
            GridStack.setupDragIn('.newWidget', { appendTo: 'body', helper: 'clone' });

            let advanceItems = [
                { id: 'defaultWidget', x: 0, y: 0, w: 5, h: 4, content: '<p class="px-4 mx-4 mt-4 pt-4"><em><b>Add KPIs as per your requirement<br/> from the dropdown-menu</b></em></p>' },
              
            ];
            advanceItems.forEach((n, i) => {
                n.id = String(i);
                n.content = `<button class="btn btn-outline-secondary" onclick="removeWidget(this.parentElement.parentElement)">X</button><br> ${n.content ? n.content : ''}`;
            });
            let advanceItemsFull;

          
            document.addEventListener('DOMContentLoaded', function () {
                document.querySelectorAll('.dropdown-item').forEach(function (item) {
                    item.addEventListener('click', function () {
                        const chartType = this.innerText.toLowerCase();
                        const chartId = chartType + 'Chart';
                        const newChart = `<canvas id="${chartId}"></canvas>`;

                        // Check if the chart already exists in advanceItems
                        const itemContent = advanceItems.find(item => item.content);
                        console.log("NEW CHART ", newChart);
                        console.log("SELECTED item.content", itemContent);
                        const existingChart = advanceItems.find(item => item.content.includes(newChart));

                        if (!existingChart) {
                            // Calculate new x and y coordinates based on existing items
                            const newX = advanceItems.length % 2 === 0 ? 8 : 0; // Alternates between 0 and 8
                            const newY = Math.floor(advanceItems.length / 2) * 2;

                            advanceItems.push({
                                id: chartId, // Add an id property to uniquely identify the chart
                                x: newX,
                                y: newY,
                                w: 6,
                                h: 4,
                                content: newChart,
                            });

                            advanceItems.forEach((n, i) => {
                                n.id = String(i);
                                if (!n.content.includes('removeWidget')) {
                                    n.content = `<button class="btn btn-outline-secondary" onclick="removeWidget(this.parentElement.parentElement)">X</button><br> ${n.content ? n.content : ''}`;
                                }
                            });

                            // Reload the grid to reflect the changes
                            grid.load(advanceItems);
                            const newItem = advanceItems.find(item => item.id === chartId);
                            if (newItem) {
                                initializeChart(newItem.content);
                            }
                            // Initialize the chart outside the grid load callback
                            initializeChart(newChart);
                        }
                    });
                });
            });


            function addEvents(grid, id) {
                let g = id !== undefined ? "grid" + id + " " : "";

                grid
                    .on("added removed change", function (event, items) {
                        let str = "";
                        items.forEach(function (item) {
                            str += " (" + item.x + "," + item.y + " " + item.w + "x" + item.h + ")";
                        });
                        console.log(
                            g + event.type + " " + items.length + " items (x,y w h):" + str
                        );
                    })
                    .on("enable", function (event) {
                        let grid = event.target;
                        console.log(g + "enable");
                    })
                    .on("disable", function (event) {
                        let grid = event.target;
                        console.log(g + "disable");
                    })
                    .on("dragstart", function (event, el) {
                        let n = el.gridstackNode;
                        let x = el.getAttribute("gs-x"); // verify node (easiest) and attr are the same
                        let y = el.getAttribute("gs-y");
                        console.log(
                            g +
                            "dragstart " +
                            (n.content || "") +
                            " pos: (" +
                            n.x +
                            "," +
                            n.y +
                            ") = (" +
                            x +
                            "," +
                            y +
                            ")"
                        );
                    })
                    .on("drag", function (event, el) {
                        let n = el.gridstackNode;
                        let x = el.getAttribute("gs-x"); // verify node (easiest) and attr are the same
                        let y = el.getAttribute("gs-y");
                     })
                    .on("dragstop", function (event, el) {
                        let n = el.gridstackNode;
                        let x = el.getAttribute("gs-x"); // verify node (easiest) and attr are the same
                        let y = el.getAttribute("gs-y");
                        console.log(
                            g +
                            "dragstop " +
                            (n.content || "") +
                            " pos: (" +
                            n.x +
                            "," +
                            n.y +
                            ") = (" +
                            x +
                            "," +
                            y +
                            ")"
                        );
                    })
                    .on("dropped", function (event, previousNode, newNode) {
                        if (previousNode) {
                            console.log(g + "dropped - Removed widget from grid:", previousNode);
                        }
                        if (newNode) {
                            console.log(g + "dropped - Added widget in grid:", newNode);
                        }
                    })
                    .on("resizestart", function (event, el) {
                        let n = el.gridstackNode;
                        let rec = el.getBoundingClientRect();
                        console.log(
                            `${g} resizestart ${n.content || ""} size: (${n.w}x${n.h
                            }) = (${Math.round(rec.width)}x${Math.round(rec.height)})px`
                        );
                    })
                    .on("resize", function (event, el) {
                        let n = el.gridstackNode;
                        let rec = el.getBoundingClientRect();
                        console.log(
                            `${g} resize ${n.content || ""} size: (${n.w}x${n.h}) = (${Math.round(
                                rec.width
                            )}x${Math.round(rec.height)})px`
                        );
                    })
                    .on("resizestop", function (event, el) {
                        let n = el.gridstackNode;
                        let rec = el.getBoundingClientRect();
                        console.log(
                            `${g} resizestop ${n.content || ""} size: (${n.w}x${n.h
                            }) = (${Math.round(rec.width)}x${Math.round(rec.height)})px`
                        );
                    });
            }


            grid.load(advanceItems);
            addEvents(grid);
            GridStack.setupDragIn('.newWidget', { appendTo: 'body', helper: 'clone' });
            initializeChart(advanceItems);

            function initializeChart(chartId) {
                console.log("in the initializeChart function", chartId, typeof (chartId))

                const ctxOccupancy = document.getElementById('occupancyChart');
                new Chart(ctxOccupancy, {
                    type: 'bar',
                    data: {
                        labels: ['Building 1', 'Building 2', 'Building 3', 'Building 4', 'Building 5'],
                        datasets: [
                            {
                                label: 'Employees',
                                data: [50, 30, 45, 25, 60],
                                backgroundColor: 'rgba(75, 192, 192, 0.7)',
                            },
                            {
                                label: 'Contractors',
                                data: [20, 15, 25, 10, 30],
                                backgroundColor: 'rgba(255, 99, 132, 0.7)',
                            },
                            {
                                label: 'Individual Tenants',
                                data: [10, 5, 15, 8, 20],
                                backgroundColor: 'rgba(255, 206, 86, 0.7)',
                            },
                        ]
                    },
                    options: {
                        scales: {
                            x: {
                                stacked: true,
                            },
                            y: {
                                stacked: true,
                                beginAtZero: true,
                            }
                        },
                        plugins: {
                            legend: {
                                display: true,
                                position: 'bottom',
                            },
                            title: {
                                display: true,
                                text: 'Occupancy',

                            },
                        },
                        responsive: true,
                        maintainAspectRatio: true,
                        layout: {
                            padding: {
                                top: 20,
                            }
                        }
                    }
                });

          

                const ctxEmployee = document.getElementById('employeeChart');
                new Chart(ctxEmployee, {
                    type: 'bubble',
                    data: {
                        datasets: [
                            {
                                label: 'Employee Distribution',
                                data: [
                                    { x: 1, y: 3, r: 10 },
                                    { x: 2, y: 2, r: 8 },
                                    { x: 3, y: 4, r: 12 },
                                    { x: 4, y: 5, r: 15 },
                                    { x: 5, y: 2, r: 8 },
                                ],
                                backgroundColor: 'rgba(75, 192, 192, 0.7)',
                            },
                        ]
                    },
                    options: {
                        scales: {
                            x: {
                                beginAtZero: true,
                            },
                            y: {
                                beginAtZero: true,
                            }
                        },
                        plugins: {
                            legend: {
                                display: true,
                                position: 'bottom',
                            },
                            title: {
                                display: true,
                                text: 'Employee Distribution',
                            },
                        },
                        responsive: true,
                        maintainAspectRatio: true,
                        layout: {
                            padding: {
                                top: 20,
                            }
                        }
                    }
                });

                const ctxRevenue = document.getElementById('revenueChart');
                new Chart(ctxRevenue, {
                    type: 'pie',
                    data: {
                        labels: ['Employees', 'Contractors', 'Individual Tenants'],
                        datasets: [{
                            data: [60, 25, 15],
                            backgroundColor: ['rgba(75, 192, 192, 0.7)', 'rgba(255, 99, 132, 0.7)', 'rgba(255, 206, 86, 0.7)'],
                        }]
                    },
                    options: {
                        plugins: {
                            legend: {
                                display: true,
                                position: 'bottom',
                            },
                            title: {
                                display: true,
                                text: 'Revenue',
                            },
                        },
                        responsive: true,
                        maintainAspectRatio: true,
                        layout: {
                            padding: {
                                top: 20,
                            }
                        }
                    }
                });

            


            }


            grid.on('added removed change', function (e, advanceItems) {
                let str = '';
                advanceItems.forEach(function (item) { str += ' (x,y)=' + item.x + ',' + item.y; });
                // console.log(e.type + ' ' + advanceItems.length + ' advanceItems:' + str);
            });



            function saveFullGrid() {
                try {
                    // Save the positions of the widget (x, y) coordinates and the content of the widgets (HTML content)
                    advanceItemsFull = grid.save(true, true);

                    // Stringify and store the advanceItemsFull object in localStorage
                    localStorage.setItem('gridData', JSON.stringify(advanceItemsFull));

                    console.log("advanceItems after Saving => ", advanceItemsFull);
                    console.log("saveFullGrid  => ", JSON.stringify(advanceItemsFull, null, '  '));
                } catch (error) {
                    console.error('Error saving full grid:', error);
                    // Provide user feedback or handle the error accordingly
                }
            }


            function loadFullGrid() {
                try {
                    if (!advanceItemsFull) {
                        let localStorageGridData = localStorage.getItem("gridData");

                        // Parse the JSON string retrieved from localStorage
                        advanceItemsFull = JSON.parse(localStorageGridData);

                        // Check if parsing was successful and if it has the expected structure
                        if (advanceItemsFull && advanceItemsFull.children) {
                            grid.removeAll();
                            grid.load(advanceItemsFull.children);
                            advanceItemsFull.children.forEach((item) => {
                                initializeChart(item.content);
                            });
                        } else {
                            console.error('Invalid data format in localStorage.');
                        }
                    } else {
                        // Your existing code for the case when advanceItemsFull is already defined
                        grid.removeAll();
                        grid.load(advanceItemsFull.children);
                        advanceItemsFull.children.forEach((item) => {
                            initializeChart(item.content);
                        });
                    }
                } catch (error) {
                    console.error('Error loading full grid:', error);
                    // Provide user feedback or handle the error accordingly
                }
            }


            // Reset function
            function clearGrid() {
                grid.removeAll();
                advanceItems = [
                    { x: 0, y: 0, w: 5, h: 4, content: '<p class="px-4 mx-4 mt-4 pt-4"><em><b>Add KPIs as per your requirement<br/> from the dropdown-menu</b></em></p>' },
                ];
                advanceItems.forEach((n, i) => {
                    n.id = String(i);
                    n.content = `<button class="btn btn-outline-secondary" onclick="removeWidget(this.parentElement.parentElement)">X</button><br> ${n.content ? n.content : ''}`;
                });

                grid.load(advanceItems);
            }

            function removeWidget(el) {
                // TEST removing from DOM first like Angular/React/Vue would do
                console.log("el", el);
                el.remove();
                grid.removeWidget(el, true);
            }

        </script>


     
    </div>
</body>

</html>



<?php
$this->registerJsFile('https://cdn.jsdelivr.net/npm/chart.js', ['position' => \yii\web\View::POS_HEAD]);
?>


1

There are 1 best solutions below

0
MT-Dev On

I managed to resolve the chart initialization issue. Basically in my below function i was adding the selected chart to advanceItems array and was having a single function for chart initialization.

I created separate functions for the initialization of every chart and extracted the selected chart id's from the canvas element in the advanceItems array and calling that function for each canvasElement selected. below is the updated code that worked


 document.addEventListener('DOMContentLoaded', function () {
                document.querySelectorAll('.dropdown-item').forEach(function (item) {
                    item.addEventListener('click', function () {
                        const chartType = this.innerText.toLowerCase();
                        const chartId = chartType + 'Chart';
                        // console.log(chartId);
                        // console.log(typeof (chartId));
                        const newChart = `<canvas id="${chartId}"></canvas>`;

                        // Check if the chart already exists in advanceItems
                        const itemContent = advanceItems.find(item => item.content);
                        console.log("NEW CHART ", newChart);
                        console.log("SELECTED item.content", itemContent);
                        const existingChart = advanceItems.find(item => item.content.includes(newChart));

                        if (!existingChart) {
                            // Calculate new x and y coordinates based on existing items
                            const newX = advanceItems.length % 2 === 0 ? 8 : 0; // Alternates between 0 and 8
                            const newY = Math.floor(advanceItems.length / 2) * 2;

                            advanceItems.push({
                                id: chartId, // Add an id property to uniquely identify the chart
                                x: newX,
                                y: newY,
                                w: 6,
                                h: 4,
                                content: newChart,
                            });

                            advanceItems.forEach((n, i) => {
                                n.id = String(i);
                                if (!n.content.includes('removeWidget')) {
                                    n.content = `<button class="btn btn-outline-secondary" onclick="removeWidget(this.parentElement.parentElement)">X</button><br> ${n.content ? n.content : ''}`;
                                }
                            });

                            // Reload the grid to reflect the changes
                            grid.load(advanceItems);


                            // Mapping between chart IDs and initialization functions
                            const chartInitializationMap = {
                                'occupancyChart': initializeOccupancyChart,
                                'roomsChart': initializeRoomsChart,
                                'contractsChart': initializeContractsChart,
                                'employeeChart': initializeEmployeeChart,
                                'revenueChart': initializeRevenueChart,
                                'invoicesChart': initializeInvoicesChart,
                                'paymentChart': initializePaymentChart,
                                'visitorsChart': initializeVisitorsChart,
                                'maintenanceChart': initializeMaintenanceChart,
                            };

                            // Extract canvas elements using regular expression
                            const canvasElements = advanceItems.map(selectedGraph => {
                                const matches = selectedGraph.content.match(/<canvas.*?<\/canvas>/);
                                return matches ? matches[0] : null;
                            }).filter(Boolean);

                            console.log("Canvas elements:", canvasElements);

                            // Call the corresponding initialization functions based on the canvas IDs
                            canvasElements.forEach(canvasElement => {
                                const chartIdMatch = canvasElement.match(/id="([^"]+)"/);
                                if (chartIdMatch) {
                                    const chartId = chartIdMatch[1];
                                    const initializationFunction = chartInitializationMap[chartId];
                                    if (initializationFunction) {
                                        initializationFunction();
                                    }
                                }
                            });




                        }
                    });
                });
            });


separate chart functions were made as under:

  function initializeOccupancyChart(chartContent) {
                // Add your existing chart initialization code here
                // Make sure that this code is executed after the grid is loaded
                // You might also need to modify this function to target the correct chart container
                // based on the chartId.
                console.log("in the initializeOccupancyChart function", chartContent, typeof (chartContent))

                const ctxOccupancy = document.getElementById('occupancyChart');
                new Chart(ctxOccupancy, {
                    type: 'bar',
                    data: {
                        labels: ['Building 1', 'Building 2', 'Building 3', 'Building 4', 'Building 5'],
                        datasets: [
                            {
                                label: 'Employees',
                                data: [50, 30, 45, 25, 60],
                                backgroundColor: 'rgba(75, 192, 192, 0.7)',
                            },
                            {
                                label: 'Contractors',
                                data: [20, 15, 25, 10, 30],
                                backgroundColor: 'rgba(255, 99, 132, 0.7)',
                            },
                            {
                                label: 'Individual Tenants',
                                data: [10, 5, 15, 8, 20],
                                backgroundColor: 'rgba(255, 206, 86, 0.7)',
                            },
                        ]
                    },
                    options: {
                        scales: {
                            x: {
                                stacked: true,
                            },
                            y: {
                                stacked: true,
                                beginAtZero: true,
                            }
                        },
                        plugins: {
                            legend: {
                                display: true,
                                position: 'bottom',
                            },
                            title: {
                                display: true,
                                text: 'Occupancy',

                            },
                        },
                        responsive: true,
                        maintainAspectRatio: true,
                        layout: {
                            padding: {
                                top: 20,
                            }
                        }
                    }
                });
            }

            function initializeRoomsChart(chartContent) {
                // Add your existing chart initialization code here
                // Make sure that this code is executed after the grid is loaded
                // You might also need to modify this function to target the correct chart container
                // based on the chartId.
                console.log("in the initializeRoomsChart function", chartContent, typeof (chartContent))

                const ctxRooms = document.getElementById('roomsChart');
                new Chart(ctxRooms, {
                    type: 'bar',
                    data: {
                        labels: ['Building 1', 'Building 2', 'Building 3', 'Building 4', 'Building 5'],
                        datasets: [
                            {
                                label: 'Vacant',
                                data: [10, 5, 8, 3, 12],
                                backgroundColor: 'rgba(255, 99, 132, 0.7)',
                            },
                            {
                                label: 'Allocated to Employees',
                                data: [20, 15, 25, 10, 30],
                                backgroundColor: 'rgba(75, 192, 192, 0.7)',
                            },
                            {
                                label: 'Rented to Contractors',
                                data: [5, 3, 6, 2, 8],
                                backgroundColor: 'rgba(255, 206, 86, 0.7)',
                            },
                            {
                                label: 'Rented to Individual Tenants',
                                data: [15, 7, 12, 5, 18],
                                backgroundColor: 'rgba(0, 123, 255, 0.7)',
                            },
                        ]
                    },
                    options: {
                        scales: {
                            x: {
                                stacked: true,
                            },
                            y: {
                                stacked: true,
                                beginAtZero: true,
                            }
                        },
                        plugins: {
                            legend: {
                                display: true,
                                position: 'bottom',
                            },
                            title: {
                                display: true,
                                text: 'Rooms',
                            },
                        },
                        responsive: true,
                        maintainAspectRatio: true,
                        layout: {
                            padding: {
                                top: 20,
                            }
                        }
                    }
                });
            }