DataTables Render function returns Undefined data

DataTables Render function returns Undefined data

Hamjam31Hamjam31 Posts: 15Questions: 3Answers: 0

Hi I'm new to DataTables and just recently tried creating a simple view of some test data I have. However, when I try to implement a render function to join together first_name and last_name data, it returns both as undefined. Attached is a picture of the datatables view.
DataTables View

Code for DataTables

{% extends 'base_datatables_editor.html' %}

{% block content %}
<h1 style="text-align: center; padding-top: 1em; padding-bottom: 1em;">Mental Health Studies</h1>
<div class="row">
    <div class="col-sm-12">
        <table id="StudyDataTable" class="table table-striped table-bordered" style="width:100%">
            <thead>
                <tr>
                    <th scope="col">Name</th>
                    <th scope="col">Investigator</th>
                    <th scope="col">Start Date</th>
                    <th scope="col">Enrollment Goal</th>
                    <th scope="col">Status</th>
                    <th scope="col">Site</th>
                </tr>
            </thead>
        </table>
    </div>
</div>
<h1 style="text-align: center; padding-top: 1em; padding-bottom: 1em;">Investigators</h1>
<div class="row">
    <div class="col-sm-12">
        <table id="InvestigatorDataTable" class="table table-striped table-bordered" style="width:100%">
            <thead>
                <tr>
                    <th scope="col">Name</th>
                    <th scope="col">Email</th>
                    <th scope="col">Institution</th>
                </tr>
            </thead>
        </table>
    </div>
</div>
{% endblock content %}

{% block extra_js %}
    <script>
        var editor; 

        $(document).ready(function() {
            editor = new $.fn.dataTable.Editor( {
                ajax: "api/investigator/",
                table: '#InvestigatorDataTable',
                fields: [ {
                    label: "Last Name:",
                    name: "last_name"
                }, {
                    label: "First Name:",
                    name: "first_name"
                }, {
                    label: "Email:",
                    name: "email"
                }, {
                    label: "Institution:",
                    name: "institution"
                }] 
            });
            $('#StudyDataTable').DataTable({
                serverSide: true,
                ajax: 'api/study/?format=datatables',
                columns: [
                    {data: "name_short",},
                    {data: "investigator.last_name", orderable: true},
                    {data: "start_date", orderable: false},
                    {data: "enrollment_goal", orderable: true},
                    {data: "status",},
                    {data: "site.name",},
            ]
            });
            $('#InvestigatorDataTable').DataTable({
                "serverSide": true,
                ajax: 'api/investigator/?format=datatables',
                dom: 'Bfrtrip',
                columns: [
                    { data: null, render: function ( data, type, row ) {
                        return data.first_name+' '+data.last_name;
                    }},
                    {data: "email", orderable: false},
                    {data: "institution.name", orderable: true},
                ],
                select: true,
                buttons: [
                    { extend: "create", editor: editor },
                    { extend: "edit", editor: editor }, 
                    { extend: "remove", editor: editor }
                ]
            });
        });
    </script>
{% endblock %}

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951
    edited January 2023

    That suggests your row data doesn't have the objects first_name and last_name. You can use console.log( data ) in the render function to see what data you have.

    If you still need help then post a sample of the row data.

    Kevin

  • Hamjam31Hamjam31 Posts: 15Questions: 3Answers: 0

    Thanks for the response. Looks like you are right that first_name and last_name aren't included in the data variable for some reason. However, they are parameters within the table I created. Why are they not showing up?

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951

    Your REST API is returning last_name and first_name in the API response. The data is in the dictionary results. Datatables looks for the data in the dictionary data. I suspect your Django function is repackaging the data, due to ?format=datatables, and might not be returning the last_name and first_name objects. Use the browser's network inspector to see what is returned in the XHR response.

    Kevin

  • Hamjam31Hamjam31 Posts: 15Questions: 3Answers: 0

    Thank you very much for the help. The browser's network XHR response shows that it only returns the email and institution fields.

    api/investigator XHR Response
    {"recordsTotal":2,"recordsFiltered":2,"data":[{"email":"kolim@umn.edu","institution":{"name":"University of Minnesota","dept":"Psychiatry"}},{"email":"Noah_Philip@Brown.edu","institution":{"name":"Brown University","dept":"Psychiatry"}}],"draw":1}

    However, interestingly, the XHR response for the api/study datable returns all fields even though it is also calling the same format of data.
    {"recordsTotal":3,"recordsFiltered":3,"data":[{"name_short":"Neurotrauma","investigator":{"id":1,"last_name":"Lim","first_name":"Kelvin","email":"kolim@umn.edu","created_at":"2022-05-19T17:59:46.167754Z","institution":{"name":"University of Minnesota","dept":"Psychiatry"}},"start_date":"2022-01-01","enrollment_goal":200,"status":"active","site":{"name":"Fairview","lead":1}},{"name_short":"TMS MRI","investigator":{"id":1,"last_name":"Lim","first_name":"Kelvin","email":"kolim@umn.edu","created_at":"2022-05-19T17:59:46.167754Z","institution":{"name":"University of Minnesota","dept":"Psychiatry"}},"start_date":"2021-01-01","enrollment_goal":100,"status":"active","site":{"name":"Fairview","lead":1}},{"name_short":"TMS PTSD","investigator":{"id":2,"last_name":"Philip","first_name":"Noah","email":"Noah_Philip@Brown.edu","created_at":"2022-12-23T21:47:34.185568Z","institution":{"name":"Brown University","dept":"Psychiatry"}},"start_date":"2022-12-23","enrollment_goal":50,"status":"active","site":{"name":"Rhode Island Hospital","lead":2}}],"draw":1}

    Also to note when I specify data: "first_name", the column within the tables shows up within the XHR response.

    $('#InvestigatorDataTable').DataTable({
                    serverSide: true,
                    ajax: 'api/investigator/?format=datatables',
                    dom: 'Bfrtrip',
                    columns: [
                        {data: "first_name", render: function ( data, type, row ) {
                            return data;
                        }},
                        {data: "email", orderable: false},
                        {data: "institution.name", orderable: true},
                    ],
                    select: true,
                    buttons: [
                        { extend: "create", editor: editor },
                        { extend: "edit", editor: editor }, 
                        { extend: "remove", editor: editor }
                    ]
                });
    

    XHR Response
    {"recordsTotal":2,"recordsFiltered":2,"data":[{"first_name":"Kelvin","email":"kolim@umn.edu","institution":{"name":"University of Minnesota","dept":"Psychiatry"}},{"first_name":"Noah","email":"Noah_Philip@Brown.edu","institution":{"name":"Brown University","dept":"Psychiatry"}}],"draw":1}

    How am I able to call the render function so it calls all the fields?

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951
    edited January 2023 Answer ✓

    Also to note when I specify data: "first_name", the column within the tables shows up within the XHR response.

    Interesting. That suggests your Python Django routes look at the XHR request sent from the client for the columns defined to decide what to return. Nice feature if this is true. See the Server Side Processing Sent Parameters for details. If this is true then you will need to define all the columns you want fetched. You will need to look at your Django routes to determine if this is true. Its not a feature of Datatables but its how your Django code is built.

    You can use columns.visible to hide the columns you don't want displayed. Then define an additional column and use the code in your first code snippet to combine the columns:

                        { data: null, render: function ( data, type, row ) {
                            return data.first_name+' '+data.last_name;
                        }},
    

    Again you will need to look at your Django routes to determine your course of action.

    Kevin

  • Hamjam31Hamjam31 Posts: 15Questions: 3Answers: 0

    This helped a lot. I was finally able to get it to work by calling all the fields and then simply hiding the fields that I don't need.

    The updated code looks like this:

    {% extends 'base_datatables_editor.html' %}
    
    {% block content %}
    <h1 style="text-align: center; padding-top: 1em; padding-bottom: 1em;">Mental Health Studies</h1>
    <div class="row">
        <div class="col-sm-12">
            <table id="StudyDataTable" class="table table-striped table-bordered" style="width:100%">
                <thead>
                    <tr>
                        <th scope="col">Name</th>
                        <th scope="col">Investigator</th>
                        <th scope="col">Start Date</th>
                        <th scope="col">Enrollment Goal</th>
                        <th scope="col">Status</th>
                        <th scope="col">Site</th>
                    </tr>
                </thead>
            </table>
        </div>
    </div>
    <h1 style="text-align: center; padding-top: 1em; padding-bottom: 1em;">Investigators</h1>
    <div class="row">
        <div class="col-sm-12">
            <table id="InvestigatorDataTable" class="table table-striped table-bordered" style="width:100%">
                <thead>
                    <tr>
                        <th scope="col">First Name</th>
                        <th scope="col">Last Name</th>
                        <th scope="col">Name</th>
                        <th scope="col">Email</th>
                        <th scope="col">Institution</th>
                    </tr>
                </thead>
            </table>
        </div>
    </div>
    {% endblock content %}
    
    {% block extra_js %}
        <script>
            var editor; 
    
            $(document).ready(function() {
                editor = new $.fn.dataTable.Editor( {
                    ajax: "api/investigator/",
                    table: '#InvestigatorDataTable',
                    idSrc: "id", 
                    fields: [ {
                        label: "Last Name:",
                        name: "last_name"
                    }, {
                        label: "First Name:",
                        name: "first_name"
                    }, {
                        label: "Email:",
                        name: "email"
                    }, {
                        label: "Institution:",
                        name: "institution"
                    }] 
                });
                $('#StudyDataTable').DataTable({
                    serverSide: true,
                    ajax: 'api/study/?format=datatables',
                    dom: 'Bfrtrip',
                    columns: [
                        {data: "name_short",},
                        //{data: "investigator.last_name", orderable: true},
                        {data: "investigator", render: function ( data, type, row ) { 
                            return data.last_name + ", " + data.first_name; 
                        }},
                        {data: "start_date", orderable: false},
                        {data: "enrollment_goal", orderable: true},
                        {data: "status",},
                        {data: "site.name",},
                ]
                });
                $('#InvestigatorDataTable').DataTable({
                    serverSide: true,
                    ajax: 'api/investigator/?format=datatables',
                    dom: 'Bfrtrip',
                    columns: [
                        {data: "last_name", },
                        {data: "first_name",},
                        {data: null, render: function ( data, type, row ) {
                            return data.first_name + " " + data.last_name
                        }},
                        {data: "email", orderable: false},
                        {data: "institution.name", orderable: true},
                    ],
                    columnDefs: [
                        { targets: [2, 3, 4,], visible: true},
                        { targets: '_all', visible: false }
                    ],
                    select: true,
                    buttons: [
                        { extend: "create", editor: editor },
                        { extend: "edit", editor: editor }, 
                        { extend: "remove", editor: editor }
                    ]
                });
            });
        </script>
    {% endblock %}
    

    Another interesting note is that when I added a render function to the study datatable, it was able to display name function I wanted right away. Perhaps there is a difference with render being able to call data that is nested vs render for data that is in different columns?

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951

    Take a look at the columns.render docs. There is a row parameter which contains all the data in the row. If you define data: "investigator", for example, then you need to use row.last_name. However if you define data: null then there is no specific column data for the column so data is the full row too. Its best to get in the habit of using row to access the full row of data.

    Kevin

Sign In or Register to comment.