Unable to get row data after first AJAX call, nested tables.

Unable to get row data after first AJAX call, nested tables.

DayvinhoDayvinho Posts: 7Questions: 1Answers: 0
edited August 2020 in Free community support

I am having trouble retrieving row data after the first successful call. I am getting the "Cannot read property 'blah' of undefined". I am guessing that this is a caching related issue but have no idea how to fix this or proceed, any help will be very welcome! Thanks.

    function getMarkerData() {
        var childTable;
        var classes = $('#searchClasses').val();
        var lats = [];
        var lons = [];
        markers.forEach(function(marker) {
            var markerlatlon = marker.getLatLng();
            lats.push(markerlatlon.lat);
            lons.push(markerlatlon.lng);
        });
        showDataTable();
        if ($('#datatable3').text().length != 0) {
            var DT3 = $('#datatable3').text();
            console.log(DT3);
            $(DT3).DataTable().destroy();
        }
        if ($('#datatable2').text().length != 0) {
            var DT2 = $('#datatable2').text();
            console.log(DT2);
            $(DT2).DataTable().destroy();
        }
        if ($.fn.DataTable.isDataTable('#postcodeData')) {
            $('#postcodeData').DataTable().rows().invalidate();
            $('#postcodeData').DataTable().destroy();
        }
        console.log();
        var table = $('#postcodeData').DataTable({
            'ajax' : {
                'url' : '/admin/postcodesearches/_get_searches',
                'type' : 'POST',
                'data' : {
                    classes : classes,
                    lats : lats,
                    lons : lons
                },
                'dataSrc' : ''
            },
            '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' : 'postcode'},
                {'data' : 'Total5'},
                {'data' : 'Total10'},
                {'data' : 'Total20'},
                {'data' : 'comp_count'}
            ],
            "order": [[1, 'asc']]
        });
        $('#postcodeData tbody').on('click', 'td.details-control', function() {
            var tr = $(this).closest('tr');
            var tdi = tr.find("i.fa");
            var row = table.row(tr);
            var rowData1 = row.data();
            if (row.child.isShown()) {
                row.child.hide();
                tr.removeClass('shown');
                $('#pt' + rowData1.postcode).DataTable().destroy();
                tdi.first().removeClass('fa-minus-square');
                tdi.first().addClass('fa-plus-square');
            }
            else {
                row.child(formatPrimary(rowData1)).show();
                var postcode = rowData1.postcode;
                var childTableID = '#pt' + postcode
                childTable = $(childTableID).DataTable({
                    dom : 't',
                    ajax : {
                        url : '/admin/postcodesearches/_get_nested_searches',
                        type : 'POST',
                        data : {
                            postcode : postcode,
                            class_id : rowData1.parent_ids,
                            df_type : 'PRIMARY'
                        },
                        dataSrc : ''
                    },
                    columns : [
                        {
                            className : 'details-control1',
                            orderable : false,
                            data : null,
                            defaultContent : '',
                            render : function() {
                                return '<i class="fa fa-plus-square" aria-hidden="true"></i>';
                            },
                            width : '15px'
                        },
                        { data : 'class_name'},
                        { data : 'Total5'},
                        { data : 'Total10'},
                        { data : 'Total20'},
                        { data : 'comp_count'}
                    ],
                    select : false,
                    order : [[1, 'asc']]
                });
                tr.addClass('shown');
                tdi.first().removeClass('fa-plus-square');
                tdi.first().addClass('fa-minus-square');
                $('#datatable2').html(childTableID);
            }
        });
        $('tbody').on('click', 'td.details-control1', function() {
            var tr = $(this).closest('tr');
            var tdi2 = tr.find("i.fa");
            var row = childTable.row(tr);
            var rowData2 = row.data();
            if (row.child.isShown()) {
                row.child.hide();
                tr.removeClass('shown');
                $('#ct' + rowData2.parent_id_).DataTable().destroy();
                tdi2.first().removeClass('fa-minus-square');
                tdi2.first().addClass('fa-plus-square');
            }
            else {
                row.child(formatClass(rowData2)).show();
                var parent_id = rowData2.parent_id_;
                var childTable2ID = '#ct' + parent_id
                childTable2 = $(childTable2ID).DataTable({
                    dom : 't',
                    ajax : {
                        url : '/admin/postcodesearches/_get_nested_searches',
                        type : 'POST',
                        data : {
                            postcode : rowData2.postcode,
                            class_id : parent_id,
                            df_type : 'CLASS'
                        },
                        dataSrc : ''
                    },
                    columns : [
                        {
                            className : '',
                            orderable : false,
                            data : null,
                            defaultContent : ''
                        },
                        { data : 'class_name' },
                        { data : 'Total5' },
                        { data : 'Total10' },
                        { data : 'Total20' },
                        { data : 'comp_count' }
                    ],
                    select : false,
                    order : [[1, 'asc']]
                });
                tr.addClass('shown');
                tdi2.first().removeClass('fa-plus-square');
                tdi2.first().addClass('fa-minus-square');
                $('#datatable3').html(childTable2ID);
            }
        });
    }
</script>

This question has accepted answers - jump to:

Answers

  • kthorngrenkthorngren Posts: 21,166Questions: 26Answers: 4,921
    edited August 2020

    There is a lot of code there without context of what you are doing when you get the error. Is the problem in line 71 or line 133 or somewhere else?

    The best thing to do is post a link to your page or a test case so we can take a look. Otherwise you will need to debug the code flow to find out what is undefined.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Let us know what you find.

    Kevin

  • DayvinhoDayvinho Posts: 7Questions: 1Answers: 0

    Hi Kevin,

    Line 70 is where the error appears but that formatting function is also trying to access

    rowData.postcode

    The first time I generate the nested DataTables by calling this function, everything works as expected. If I then submit another search, which runs this function, it fails. When I

    console.log(rowData)

    the log shows

    undefined

  • kthorngrenkthorngren Posts: 21,166Questions: 26Answers: 4,921
    edited August 2020

    Line 70 has this: row.child(formatPrimary(rowData1)).show();

    Are you saying the error is occurring in the formatPrimary() function? Maybe I'm missing it but I don't see that function in your posted code. Please post that function if that is where the error is occurring.

    If I had access to the running code I would follow the backward path of where rowData comes from to find the source of the undefined value. Without actually being able to work with the code and see what its doing it will be very difficult for us to debug.

    Kevin

  • DayvinhoDayvinho Posts: 7Questions: 1Answers: 0
    edited August 2020

    rowData1 comes from line 61 and as I said, that function is trying to access
    rowData1.postcode

    function formatPrimary(d) {
            var childTable = '<table id="pt' + d.postcode + '" class="display compact nowrap w-100" width="100%">' +
                '<thead style="display:none"></thead >' +
                '</table>';
            return $(childTable).toArray();
        }
    

    The issue is, it works fine on the first search, but any subsequent searches the data from the row is not being assigned to rowData1. The error is thrown at the first instance I am trying to access any of the returned data.

    Upon the second search, the inital DataTable is shown just fine, with the correct data inside, however when clicking to expand this row line 61 is not assigning the row data to the variable, thus resulting in this variable being undefined.

    I have more or less followed this: http://live.datatables.net/mukirowi/180/edit with the only major difference being that the user can alter some search parameters which changes the search results data within the table.

    If this explanation does not help I will look to recreating my problem in live.datatables.

  • kthorngrenkthorngren Posts: 21,166Questions: 26Answers: 4,921

    rowData1 comes from line 61 and as I said, that function is trying to access
    rowData1.postcode

    I get the basic flow of the code and do see that. But why is it undefined? Its difficult to say without actually being able to debug the running code.

    I have more or less followed this: http://live.datatables.net/mukirowi/180/edit

    I remember that thread and code. Take a look at the thread and how complicated it was to help the person. There are a lot of things going on with that code and, without being able to work with it, it will be difficult to debug. If you haven't done so read through the thread, it may help you find the undefined.

    Kevin

  • DayvinhoDayvinho Posts: 7Questions: 1Answers: 0
    edited August 2020

    Hi Kevin,

    I have reproduced the error: http://live.datatables.net/xoyifijo/2/edit

    I have only included one level of nesting as this is enough to reproduce the error, click "Get Searches" and the + icon works as expected, click "Get Searches" again and the + icon no longer works.

    Cheers,
    Dave

  • kthorngrenkthorngren Posts: 21,166Questions: 26Answers: 4,921

    Maybe something changed in your example but the Datatable is not loading and I see this error:

    Uncaught ReferenceError: testData is not defined

    Can you fix the error so we can see the issue please?

    Kevin

  • DayvinhoDayvinho Posts: 7Questions: 1Answers: 0
    edited August 2020
  • kthorngrenkthorngren Posts: 21,166Questions: 26Answers: 4,921
    Answer ✓

    Thanks for the test case. It helps a lot to understand the problem. At least I think I understand :smile:

    Your code snippet doesn't show this but you have a Get Searches button which when clicked runs the above getMarkerData() function that destroys and re-initializes a new Datatable. Also you are activating this new click event:

    $('#postcodeData tbody').on('click', 'td.details-control', function() {

    When you click the details-control button I believe the original event is executed first because it is not removed. Since that table doesn't exist you are getting undefined. You need to turn off the click event before establishing the new event, like this:

    $('#postcodeData tbody').off().on('click', 'td.details-control', function() {

    Here is the updated example:
    http://live.datatables.net/yipomaqi/1/edit

    Kevin

  • DayvinhoDayvinho Posts: 7Questions: 1Answers: 0

    Cheers Kevin, for some reason when I add .off() to my project it is no longer registering a click on the + icon?

  • kthorngrenkthorngren Posts: 21,166Questions: 26Answers: 4,921
    Answer ✓

    Maybe that is not a good place in your project. Maybe turn it off before you destroy the Datatable, for example:
    http://live.datatables.net/rujapidi/1/edit

    Note that I removed the .off() from this statement:
    $('#postcodeData tbody').off().on('click', 'td.details-control', function() {

    And turned off the click event here:

      if ($.fn.DataTable.isDataTable('#postcodeData')) {
        $('#postcodeData tbody').off('click', 'td.details-control');
        $('#postcodeData').DataTable().destroy();
      }
    

    Kevin

  • DayvinhoDayvinho Posts: 7Questions: 1Answers: 0

    Kevin, its working, you are a gent and a scholar! Thank you so much for your help on this, really appreciated.

This discussion has been closed.