Error when handling REST DELETE response

Error when handling REST DELETE response

winagentswinagents Posts: 1Questions: 1Answers: 0

Hello,

I'm trying to integrate DataTables Editor with existing RESTful API of Django backend. I managed to bind the table editor to the API and can create, edit and delete records now. However, when I delete a record I get the following error:

Uncaught TypeError: Cannot read property 'data' of null
V7t.m6s.o6s.f._legacyAjax   @   dataTables.editor.js:372
V7t.m6s.o6s.f._submit.e.(anonymous function).(anonymous function).v5a   @   dataTables.editor.js:397
f.Callbacks.o   @   jquery.min.js:2
f.Callbacks.p.fireWith  @   jquery.min.js:2
w   @   jquery.min.js:4
f.support.ajax.f.ajaxTransport.c.send.d

My server receives DELETE request and actually removes the specified record. The problem appears when the editor handles HTTP DELETE response. As I see in JavaScript console, the editor sends the HTTP DELETE request with URL http://localhost:8000/core/api/location/47/?action=remove&id%5B%5D=47 and receives reply with HTTP status code 204 and an empty response body. I have the following JavaScript:

        <link type="text/css" rel="stylesheet" href="https://cdn.datatables.net/1.10.9/css/jquery.dataTables.min.css" />
        <link type="text/css" rel="stylesheet" href="/static/css/buttons.dataTables.min.css" />
        <link type="text/css" rel="stylesheet" href="/static/css/select.dataTables.min.css" />
        <link type="text/css" rel="stylesheet" href="/static/css/editor.dataTables.min.css" />

        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
        <script type="text/javascript" src="https://cdn.datatables.net/1.10.9/js/jquery.dataTables.min.js"></script>    
    
        <script type="text/javascript" src="/static/js/dataTables.select.js"></script>
        <script type="text/javascript" src="/static/js/dataTables.buttons.js"></script>
        <script type="text/javascript" src="/static/js/dataTables.editor.js"></script>
        
    <script>
        var editor; 

        $(document).ready(function() {

            var ajaxBase = {
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                dataSrc: "",
                data: function ( d ) {
                            return JSON.stringify( d.data );
                        }
                },      
    
            editor = new $.fn.dataTable.Editor( {
                legacyAjax: true,
                idSrc: "id",
                dataSrc: "",
                ajax: {
                    
                    create: $.extend( true, {}, ajaxBase, {

                        type: 'POST',
                        url:  '/core/api/location/',

                    }),
                    edit: $.extend( true, {}, ajaxBase, {
                        type: 'PUT',
                        url:  '/core/api/location/_id_/'
                    }),
                    remove: $.extend( true, {}, ajaxBase, {
                        type: 'DELETE',
                        url:  '/core/api/location/_id_/',
                        dataSrc: "",
                    }),
                },
                table: "#tbl",
                fields: [ 
                    {
                        label: "Name:",
                        name: "name"
                    }, {
                        label: "Description:",
                        name: "description"
                    }
                ]
            } );
            
            editor.on( 'submitSuccess', function ( e, type ) {
                table.ajax.reload();
            } );
            
            var table = $('#tbl').DataTable( {
                select: true,
                dom: "Bfrtip",

                "ajax": {
                    "url": "/core/api/location/",
                    "dataSrc": ""
                },
                "columns": [
                    { "data": "id" },
                    { "data": "name" },
                    { "data": "description" },
                    
                ],
                "buttons": [
                    { extend: "create", editor: editor },
                    { extend: "edit",   editor: editor },
                    { extend: "remove", editor: editor }
                ]
            } );
        } );
    </script>

And HTML:

<div class="content">
    <table id="tbl" class="display" cellspacing="0" width="100%">
        <thead><tr><th>Id</th><th>Name</th><th>Description</th></tr></thead>
        <tbody></tbody>
    </table>            
</div>

The DataTables Debugger reference code is 'agelul' (http://debug.datatables.net/agelul).

Also I found a strange difference in URLs for PUT and DELETE requests. In spite of the fact that the URLs for both methods are identical in JavaScript, the editor actually includes URL parameters to DELETE request. The URL for DELETE is http://localhost:8000/core/api/location/47/?action=remove&id%5B%5D=47, but for PUT method it equals to http://localhost:8000/core/api/location/47/

Could you please help me to resolve the issue?

Answers

  • allanallan Posts: 61,822Questions: 1Answers: 10,129 Site admin

    Also I found a strange difference in URLs for PUT and DELETE requests. In spite of the fact that the URLs for both methods are identical in JavaScript, the editor actually includes URL parameters to DELETE request.

    This is because some servers do not support a body in a DELETE request - so there is no other way to send the server information, other than to pass them in the query string. The HTTP spec is ambiguous here, some servers support it, some don't... The following two links provide some details:

    My server receives DELETE request and actually removes the specified record. The problem appears when the editor handles HTTP DELETE response

    What is happening here is that since there is no data returned from the server, and Editor expects valid JSON,we enter a situation which is undefined in the existing Editor code. jQuery will normally throw an error if JSON is requested but not given - however it appears to have special handling for 204 and will in fact give undefined as the "json"!

    The way to address this is to slightly modify how Editor sets up the Ajax call - specifically in the Editor.prototype._ajax function there is an opts variable that is defined at the top of the function. If we replace that with the following it will work as expected:

        var opts = {
            type:     'POST',
            dataType: 'json',
            data:     null,
            error:    error,
            success:  function ( json, status, xhr ) {
                if ( xhr.status === 204 ) {
                    json = {};
                }
                success( json );
            }
        };
    

    You can apply this patch directly, or use it from the next release of Editor will will be the latter part of next week.

    Thanks for bringing this up!

    Regards,
    Allan

This discussion has been closed.