Uncaught TypeError: Cannot read property '_aData' of undefined

Uncaught TypeError: Cannot read property '_aData' of undefined

whuangwhuang Posts: 9Questions: 5Answers: 0

Hi,

I have a JQuery DataTables that shows parent/child detailed. User can click the expand/collapse icon on the parent row and another datatable will be shown up with the details info.

Everything works perfectly when the page first time loaded. I also have some custom filters i.e. status on the page to filter the table and it basically is calling the API to get the data and call the InitTable() to refresh the whole table from frontend. The issue is after the filters is selected, the expand/collapse stop working. The icon will still be toggled but the details table did not show up. I got the "Uncaught TypeError: Cannot read property '_aData' of undefined" error when running inspection in Chrome.

Here is the code:

<script type="text/javascript">
    $(function () {
        var selected1 = [];
        $('#permitStatues').multiselect({
            selectAllValue: 'multiselect-all',
            enableCaseInsensitiveFiltering: false,
            enableFiltering: false,
            onChange: function () {
                selected1 = $('#permitStatues').val();
                $('#selectedStatues').val(selected1);
                InitTable();
            }
        });

        $('#Requestor').change(function () {
            InitTable();
        });

        $("#Status").change(function () {
            InitTable();
        });

        InitTable();
    });

    //Return table with id generated from row's name field
    function format(rowData) {
        return '<table id="' + rowData.JobId + '" class="table table-striped table-hover table-condensed table-bordered"></table>';
    }

    function InitTable() {
        $('#permitrequests').DataTable().destroy();
        var permitStatues = $('#permitStatues').val();
        var requestor = $('#Requestor').val();

        var tblpermitrequests = $('#permitrequests').DataTable({
            "destroy": true,
            "lengthMenu": [[10, 20, 25, 50, -1], [10, 20, 25, 50, "All"]],
            "search": {
                "caseInsensitive": true
            },
            "order": [[ 1, "asc" ]], //default sorting by site name
            "stateSave": true,
            "iDisplayLength": 20,
            "processing": true,
            "serverSide": true,
            "ajax": {
                "url": "@Url.HttpRouteUrl("ActionApi", new { controller = "Job", action = "GetPermitJobs", area = "" })",
                "data": { permitStatues: permitStatues, requestor: requestor },
                "type": "POST"
            },
            "columns": [
                {
                    "className": 'details-control',
                    "orderable": false,
                    "data": null,
                    "defaultContent": '',
                    "render": function () {
                        return '<i class="fa fa-plus-square" aria-hidden="true"></i>';
                    },
                    width: "15px"
                },
                { "data": "JobNumber" },
                { "data": "JobName" },
                { "data": "LocationName" },
                { "data": "CustomerName" },
                { "data": "ProjectManager" },
                { "data": "Foreman" },
                { "data": "Engineer" },
                { "data": "ScheduleStartDate" },
                { "data": "RequestCount" }
            ]
        });

        // Add event listener for opening and closing first level childdetails
        $('#permitrequests tbody').on('click', 'td.details-control', function () {
            var tr = $(this).closest('tr');
            var tdi = tr.find("i.fa");
            var row = tblpermitrequests.row(tr);
            var rowData = row.data();

            if (row.child.isShown()) {
                // This row is already open - close it
                row.child.remove();
                tr.removeClass('shown');
                tdi.first().removeClass('fa-minus-square');
                tdi.first().addClass('fa-plus-square');
                // Destroy the Child Datatable
                $('#' + rowData.JobId).DataTable().destroy();
            }
            else {
                // Open this row
                row.child(format(rowData)).show();
                var id = rowData.JobId;

                var permitrequesttable = $('#' + id).DataTable({
                    "destroy": true,
                    "order": [[1, "asc"]],
                    dom: "t",
                    "processing": true,
                    "serverSide": true,
                    "ajax": {
                        "url": "@Url.HttpRouteUrl("ActionApi", new { controller = "PermitRequest", action = "GetPermitRequests", area = "" })",
                        "data": { JobId: rowData.JobId },
                        "type": "POST"
                    },
                    columns: [
                        {
                            title: 'Action',
                            "render":
                                function (data, type, row) {
                                    if (type === 'display') {
                                        if (isAdministrator) {
                                            var actions = "<a class='view-permitrequest' href='/PermitRequest/Detail/" + row.Id + "'>"
                                                + "<span class='glyphicon glyphicon-search' title='View/Edit permit request'></span></a>"
                                                + "<span class='glyphicon glyphicon-trash delete-permitrequest' title='Delete Permit Request'></span>";
                                            return actions;
                                        }
                                        else if (isPM) {
                                            var actions = "<a class='view-permitrequest' href='/PermitRequest/Detail/" + row.Id + "'>"
                                                + "<span class='glyphicon glyphicon-search' title='View/Edit permit request'></span></a>";
                                            return actions;
                                        }
                                        else {
                                            var actions = "<a class='view-permitrequest' href='/PermitRequest/Detail/" + row.Id + "'>"
                                                + "<span class='glyphicon glyphicon-search' title='View/Edit permit request'></span></a>";
                                            return actions;
                                        }
                                    }
                                },
                            "sortable": false,
                            "class": "grid-actions"
                        },
                        { data: "Name", title: 'Permit Name' },
                        { data: "Requestor", title: 'Requestor' },
                        { data: "FSR", title: 'FSR' },
                        { data: "StatusName", title: 'Status' },
                        { data: "LocationName", title: 'Location' },
                        { data: "RequiredDate", title: 'Required Date', render: formatDate },
                        { data: "ExpiryOn", title: 'Expiry On', render: formatDate },
                        { data: "InspectionCount", title: 'Inspections' },
                        { data: "DocumentCount", title: 'Documents' }
                    ],
                    scrollY: '100px',
                    select: true,
                });

                tr.addClass('shown');
                tdi.first().removeClass('fa-plus-square');
                tdi.first().addClass('fa-minus-square');
            }
        });
    }
</script>

Here is the error screenshot and looks like the error is on this line: var rowData = row.data();

Answers

  • kthorngrenkthorngren Posts: 21,328Questions: 26Answers: 4,949

    Uncaught TypeError: Cannot read property '_aData' of undefined

    This sounds more like an error that would occur while adding data to the Datatable. Without actually seeing the page and your data it will be hard to say what is wrong. Can you post a link to your page? Otherwise you can use console.log statements or the browser's debugger to trace through the code to find out what is undefined.

    If you think its var rowData = row.data(); that is the problem then try putting a console.log( rowData ); after it to see if it outputs anything or if the error occurs first.

    Kevin

  • whuangwhuang Posts: 9Questions: 5Answers: 0

    Hi Kevin,

    Thanks for the response.

    I added the console.log(rowData) and watched the data in the console. I noticed that when the InitTable() has been called after the first time, the datatables seems still holding the original data not the new data from Ajax Call. I found this issue because when I clicked the row, the console log give me totally different value which comes from the same row number of the first time call.

    So this leads me to try to destroy and re-load the whole datatables using the link here: https://stackoverflow.com/questions/32713612/jquery-datatables-destroy-re-create but seems still no luck.

    Here is the code I added for my case:

            if ($.fn.DataTable.isDataTable('#permitrequests')) {
            $('#permitrequests').DataTable().destroy();
            }
            $('#permitrequests tbody').empty();
    

    I also tried to use clear() as below but datatables gave me an error.
    $('#permitrequests').DataTable().clear();

    No sure which way to go now. Please advise.

    Thanks,

  • colincolin Posts: 15,240Questions: 1Answers: 2,599

    We're happy to take a look, but as per the forum rules, please link to a test case - a test case that replicates the issue will ensure you'll get a quick and accurate response. Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.

    Cheers,

    Colin

  • whuangwhuang Posts: 9Questions: 5Answers: 0

    Hi Colin,

    Thanks for the update.

    After playing around the issue a bit more, I actually have it solved.

    The solution is to destroy and empty the child table before re-creating it.

        var id = rowData.JobId;
        $('#' + id).DataTable().destroy();
        $('#' + id + ' tbody').empty();
    
This discussion has been closed.