Inline Editor does not work and the Insert, Edit, Delete buttons are not displayed.

Inline Editor does not work and the Insert, Edit, Delete buttons are not displayed.

KostasRKostasR Posts: 24Questions: 5Answers: 0

Hello all,

I activated the inline editor and also the buttons. The buttons are unfortunately not displayed.
With the Inline Editor I get an error message: "Uncaught Type Error: Cannot read property 'node' of undefined"

Without the inline editor no error message comes. The buttons are still not displayed.

I have not installed the package https://editor.datatables.net/download/download?type=php
but https://datatables.net/download/index a custom package created with the settings:

Step1: Bootstrap 4
Step2: DataTables
Extensions: Responsive, KeyTable and Select
Step3: Minify and Concatenate

Have I overlooked anything? Or do I have to use the PHP package?

// Activate an inline edit on click of a table cell
             $("#Grid1").on( 'click', 'tbody td:not(:first-child)', function (e) {
                 editor.inline( this );
             } );

buttons: [
                         { extend: 'create', editor: editor },
                         { extend: 'edit',   editor: editor },
                         { extend: 'remove', editor: editor }
                     ]

Answers

  • tangerinetangerine Posts: 3,350Questions: 37Answers: 394

    You don't appear to have the Buttons extension installed. Also, you don't want datatables.js and datatables.min.js. Just use one of them.

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    datatables.min.js. I actually use.
    The grid is also displayed but I can not go into edit mode.

        <script type="text/javascript" src="/vendor/DataTables/datatables.min.js"></script>
    
    

    I have recreated the package with the options,
    unfortunately without success. Are the buttons not included in Step 2 Editor?

    Step1: DataTables
    Step2: DataTables, Editor
    Extensions: Responsive, KeyTable and Select
    Step3: Minify and Concatenate

  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    I don't see Buttons in your directory listing, so @tangerine is correct - you need to include Buttons in your download package. They are an option in the download builder.

    Once you have them included in your download, could you show me the Javascript you are using to initialise the table please?

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Oh sorry, there are still buttons as a package, I had overlooked that.
    Sadly it still does not work.

    The html page contains two DataTables with exactly the same layout and two different data sources as a JSON array.

    Currently I have disabled Inline Editor, the buttons are active.

    Sorry I do not know exactly what you are looking for, therefore the complete function that generates the table.


    <table cellpadding="0" cellspacing="0" border="0" class="display" id="gastGrid" width="100%">
                                    <thead>
                                    <tr>
                                        <th scope="col">PassNr</th>
                                        <th scope="col">Schuetze</th>
                                        <th scope="col" class="text-right">Ringe</th>
                                        <th scope="col" class="text-center">ST</th>
                                        <th scope="col" class="text-center">MW</th>
                                        <th scope="col" class="text-center">AK</th>
                                        <th scope="col" class="text-center">SE</th>
                                        <th scope="col" class="text-right">Praezission</th>
                                        <th scope="col" class="text-right">Duell</th>
                                        <th scope="col">ScheibenNr</th>
                                        <th scope="col">Serie1</th>
                                        <th scope="col">Serie2</th>
                                        <th scope="col">Serie3</th>
                                        <th scope="col">Serie4</th>
                                    </tr>
                                    </thead>
    
                                    <tfoot>
                                    <tr>
                                        <th colspan="2" class="text-right">Gast-Ringe:</th>
                                        <th class="text-right"></th>
                                    </tr>
                                    </tfoot>
                                </table>
    
    
    heimEditor = drawDataTable("#heimGrid", heimErgebnisseArr, durchgangNr, wettkampfArr.auswerttyp, false, false);
    
    gastEditor = drawDataTable("#gastGrid", gastErgebnisseArr, durchgangNr, wettkampfArr.auswerttyp, false, false);
    
            function drawDataTable(aGrid, aData, aDurchgang, aAuswerttyp, aMitScheibenNr, aMitSerien) {
    
                     var editor = new $.fn.dataTable.Editor( {
                         data: aData,
                         fields: [
                             {
                                label: "PassNr:",
                                name: "PassNr"
                            },
                            {
                                "label": "ST:",
                                "name": "ST",
                                "type": "checkbox"
                            }
                        ]
                    } );
    
                // Activate an inline edit on click of a table cell
                //  $(aGrid).on( 'click', 'tbody td:not(:first-child)', function (e) {
                //      editor.inline( this );
                //  } );
    
                    var table = $(aGrid).DataTable( {
                        data: aData,
                        //paging: false,
                        //ordering: false,
                        //info: false,
                        //searching: true,
                        //responsive: true,
    
                        footerCallback: function ( row, data, start, end, display ){
                            var api = this.api(), data;
    
                            // Remove the formatting to get integer data for summation
                            var intVal = function ( i ) {
                                return typeof i === 'string' ?
                                    i.replace(/[\$,]/g, '')*1 :
                                    typeof i === 'number' ?
                                        i : 0;
                            };
    
                            //Total over all pages
                            total = api
                                .column( 2 )
                                .data()
                                .reduce( function (a, b) {
                                    return intVal(a) + intVal(b);
                                }, 0);
    
                            // Update footer
                            $( api.column ( 2 ).footer() ).html(total);
    
                        },
    
                        columns: [
                            {
                                data: "PassNr",
                                searchable: false,
                                sortable: false
                            },
                            {
                                data: "ST",
                                searchable: false,
                                sortable: false,
                                visible: (aDurchgang==1 ? true : false),
                                className: "text-center",
                                render: function ( data, type, row ) {
                                    if (data === true) {
                                        return '<input type="checkbox" class="editor-active" onclick="return false;" checked>';
                                    }else
                                    {
                                        return '<input type="checkbox" class="editor-active" onclick="return false;" >';
                                    }
                                    return data;
                                }
    
                            }
                         ],
                         select: true,
                         lengthChange: false,
                         buttons: [
                             { extend: 'create', editor: editor },
                             { extend: 'edit',   editor: editor },
                             { extend: 'remove', editor: editor }
                         ]
                    } );
    
                    return editor;
            }
    
    
  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    It doesn't appear that you are inserting the buttons anywhere. Most of the Editor examples use the dom option to display them, which doesn't appear to be in your code above.

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    perfect I have only dom: 'Bfrtip', inserted and already the buttons are visible.

    When I select a line and click on Edit, the editor appears but all fields are empty.
    The editor is connected to the same data source as the grid.

    If I activate the inline editor and click in a field, it will be empty.

                //Activate an inline edit on click of a table cell
                 $(aGrid).on( 'click', 'tbody td:not(:first-child)', function (e) {
                     editor.inline( this );
                 } );
    

    Do you have any idea?

    Sorry for my questions, but in the beginning it's always hard if you do not know the component. Thank you for the support.

    Regards,
    Kostas

  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    Can you give me a link to the page so I can take a look and try to understand what is going wrong there please?

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    that's not easy. :-( It's not a simple html page and currently it's not online at all.) The drawDataTable () function vom last post, does everything to draw the grid, so if there are no errors, it will probably be due to the data source?

    Can I assume that when I select a row, the editor gets the selected record to edit?

    Do I have to specify a Primary Key field?

    I will try to create a separate html page with only the editor included and the data source hard coded as an array. This could be used to test the case.

    Many thanks Allan,
    Regards,
    Kostas

  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    Do I have to specify a Primary Key field?

    Yes. Without a primary key, when you edit a row, the server wouldn't know which row to update!

    Perhaps you can show me the Editor and DataTables code you are using?

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    The html page contains two DataTables. Each DataTable has its own DataSource.

    The function drawDataTable contains everything to draw the grid.

    I do not use the server side methods. I have only a JSON array as Datasource. The editor should write all changes to the array and add new entries to the array. I will continue to process the array and send it to my server.

    I have removed some fields from the editor and DataTables code so it will not be too long.


    heimEditor = drawDataTable("#heimGrid", heimErgebnisseArr, durchgangNr, wettkampfArr.auswerttyp, false, false); gastEditor = drawDataTable("#gastGrid", gastErgebnisseArr, durchgangNr, wettkampfArr.auswerttyp, false, false); function drawDataTable(aGrid, aData, aDurchgang, aAuswerttyp, aMitScheibenNr, aMitSerien) { var editor = new $.fn.dataTable.Editor( { data: aData, fields: [ { label: "PassNr:", name: "PassNr" }, { "label": "ST:", "name": "ST", "type": "checkbox" } ] } ); // Activate an inline edit on click of a table cell $(aGrid).on( 'click', 'tbody td:not(:first-child)', function (e) { editor.inline( this ); } ); var table = $(aGrid).DataTable( { dom: 'Bfrtip', data: aData, paging: false, ordering: false, info: false, searching: false, responsive: true, footerCallback: function ( row, data, start, end, display ){ var api = this.api(), data; // Remove the formatting to get integer data for summation var intVal = function ( i ) { return typeof i === 'string' ? i.replace(/[\$,]/g, '')*1 : typeof i === 'number' ? i : 0; }; //Total over all pages total = api .column( 2 ) .data() .reduce( function (a, b) { return intVal(a) + intVal(b); }, 0); // Update footer $( api.column ( 2 ).footer() ).html(total); }, columns: [ { data: "PassNr", searchable: false, sortable: false }, { data: "ST", searchable: false, sortable: false, visible: (aDurchgang==1 ? true : false), className: "text-center", render: function ( data, type, row ) { if (data === true) { return '<input type="checkbox" class="editor-active" onclick="return false;" checked>'; }else { return '<input type="checkbox" class="editor-active" onclick="return false;" >'; } return data; } } ], select: true, lengthChange: false, buttons: [ { extend: 'create', editor: editor }, { extend: 'edit', editor: editor }, { extend: 'remove', editor: editor } ] } ); return editor; }

    Regards,
    Kostas

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    that could be interesting too.

        <!-- Bootstrap core CSS -->
        <link href="/vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
    
        <!-- Custom styles for this template -->
        <link href="form-validation.css" rel="stylesheet">
    
        <link rel="stylesheet" type="text/css" href="/vendor/DataTables/datatables.min.css"/>
    
     <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
        <script>window.jQuery || document.write('<script src="https://code.jquery.com/jquery-3.3.1.min.js"><\/script>')</script>
    
        <script src="/vendor/twbs/bootstrap/assets/js/vendor/popper.min.js"></script>
        <script src="/vendor/twbs/bootstrap/dist/js/bootstrap.min.js"></script>
        <script src="/vendor/twbs/bootstrap/assets/js/vendor/holder.min.js"></script>
    
    
        <script type="text/javascript" src="/vendor/DataTables/datatables.min.js"></script>
    

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    I have a demo online now.

    datatables.shot-contest.de/

  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    The first, and biggest issue I see, is that there is no table option in your Editor configuration. That is used to link DataTables and Editor together. Also there is no data option for Editor, so that can be dropped (it reads the data from the DataTable).

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    that was the right hint. I have added a property Table and idSrc and additionally included the PK Field ID in the data source. And already editing works fine. :-) Thanks for that.

    My PK IDs coming from the database are always> 0. For new records, I would like to generate the IDs -1, -2, etc.

    I used the event "preSubmit". Unfortunately, the ID is not written to the data source. If I click edit, the ID is always 0.

            var newID = 0;
    
            editor.on( 'preSubmit', function ( e, o, action ) {
                // https://editor.datatables.net/examples/api/clientValidation.html
                if ( action !== 'remove' ) {
    
                    // if new record set ID = newID--
                    if ( this.field( 'ID' ).val().length == 0 ) {
                        this.field( 'ID' ).val( newID-- );
                        
                        //---does not work
                        //console.log(o);
                        //o.data.id = newID--;
    
    
    
                        return true;
                    }
                }
            } );
    
    

    Regards
    Kostas

  • tangerinetangerine Posts: 3,350Questions: 37Answers: 394

    Why don't you use an auto-increment field in your database? Creating primary keys manually can be a bad idea.

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi tangerine,

    The ID field is an AutoInc field in the database.

    I do not use the server side methods. I have only a JSON array as Datasource. The editor should write all changes to the array and add new entries to the array. I will continue to process the array and send it to my server.

    When I add a new record, I have to set the primary key field to a unique value. Otherwise, the editor always allocates 0. So I can not edit the new records. Therefore I would set id= -1, -2, etc. My server would recognize a PK <0 as a new record and write it in the database without PK. Thus, the PK is assigned in the server.

    Do you have any idea why the value is not written to the dataset, or why the editor does not update the new value?

    cheers,
    Kostas

  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    preSubmit is too late to use the Editor API to set values. As the documentation notes:

    If you need to modify the data of the form using the API methods, please use the initSubmit event.

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    Unfortunately this did not work. The editor still displays ID = 0.

            editor.on( 'initSubmit', function ( e, action ) {
                if ( action !== 'remove' ) {
    
                    // if new record set ID = newID--
                    if ( editor.field( 'ID' ).val().length == 0 ) {
                        editor.field( 'ID' ).val( newID-- );
                    }
                }
            } );
    

    Can it be that I have to take this approach:
    "Ajax override - using localStorage for the data source"

    So the editor can not write directly to the local DataSet?

    regards,
    Kostas

  • tangerinetangerine Posts: 3,350Questions: 37Answers: 394

    When I add a new record, I have to set the primary key field to a unique value. Otherwise, the editor always allocates 0.

    That should not be happening.
    I can't remember how to fix that right now, but don't complicate things by creating a workaround for something that is already wrong.
    Sorry I can't be more help.

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    No problem, thank you for the help. I'm trying to understand how DataTables works. DataTables is very comprehensive and not easy to start with. Surely it's up to me and not to DataTables. :-)

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    HALT I found out that it is the primary key field!
    Every other field can be set!

            editor.on( 'initSubmit', function ( e, action ) {
                if ( action !== 'remove' ) {
    
                   //That will be not set 
                     if ( editor.field( 'ID' ).val().length == 0 ) {
                         editor.field( 'ID' ).val( 100 );
                         //editor.field( 'ID' ).val( "100" );
                     }
    
                   //That will be set
                    if ( editor.field( 'Schuetze' ).val().length == 0 ) {
                        editor.field( 'Schuetze' ).val( 'new Record' );
                    }
    
                }
            } );
    

    var editor = new $.fn.dataTable.Editor({ data: aData, table: aGrid, idSrc: 'ID', //<<< Can it be related? fields: [ { "label": "ID:", "name": "ID" },
  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    Yes, that would make sense. Editor needs to have a reference to each row of data and it keys that on the primary key value (or in the case of creating a new row, the index). Changing that value is going to cause it problems since it doesn't update its internal reference.

    Possibly what you need to do here is move back to preSubmit (sorry) and instead of attempting to use the Editor API methods to change the value, just change the value directly on the data object that preSubmit receives. That is then what will be used to submit.

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    I admire your patience with me.

    I switched to "preSubmit" the 999 is also written in element id. This can be seen through the alert. When I edit the new record, the ID is 0.

    If I do not add but only change I see the change in the editor. However, the change is not written to my DataSet. This is shown by the button "show array"

     editor.on( 'preSubmit', function ( e, data, action ) {
                if ( action !== 'remove' ) {
    
                    $.each( data.data, function ( key, values ) {
                        data.data[ key ]['ID'] = 999;
                        alert('key=' + key + '  values[\'ID\']=' + values['ID']);
                    } );
    
    
                }
            } );
    

    datatables.shot-contest.de/

    I look at this example. Is that perhaps the better way?
    https://editor.datatables.net/examples/advanced/localstorage.html
    is it possible to fill the localStore with my array? Then add new records or edit records via the editor and then write the LocalStore back to my array?

  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    Okay - I see the issue here - thanks for the link! What is happening is that Editor always takes the key from the entry in the data object, rather than from the submitted object. So what you actually need to do is:

    editor.on('preSubmit', function(e, data, action) {
        if (action === 'create') {
            $.each(data.data, function(key, values) {
                data.data[key]['ID'] = 999;
                data.data[999] = data.data[key];
                delete data.data[key];
    
                alert('key=' + key + '  values[\'ID\']=' + values['ID']);
            });
        }
    });
    

    Its convoluted I admit! I hadn't really considered the case where the end user might submit the primary key here, since it is relatively unusual as tangerine says.

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    I tested your suggestion and it works. :-)
    How can I write back the complete content of the editor in my DataSource?

    Have we misunderstood?

    I do not need the primary key. I thought DataTables needed the primary key. When the html page is called, some of the records are retrieved from the server and written to a local JSON array. Further actions add or delete more records. After this process, this JSON array is passed as a data source to the DataTables Edior. The user can edit the data and add more. Then the data from the DataTables editor is written back to the JSON array. I do not need the primary key for the entire runtime. My server can handle it if records come without a primary key. But without a primary key, the records in DataTables Editor can not be edited?

    regards,
    Kostas

  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    I do not need the primary key. I thought DataTables needed the primary key.

    DataTables itself doesn't. But typically it needs to be able to tell the server "edit row X", where X is the primary key value (otherwise the server wouldn't know what row to edit).

    Like @tangerine said above, typically I'd just let the server-side decide on the primary key. Editor will default to the current date stamp for the primary key when you create the row for a locally edited table, and you can then ignore that when you write it to the database.

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    Hi Allan,

    A date stamp would be perfect. What do I have to change so that DataTables creates a date stamp as PK?

    After all the new records and changes have been created via the editor, I have to check the data and send it to the server. Is there a way to access the Editor's internal DataSet?

    datatables.shot-contest.de/

    Regards,
    Kostas

  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    Editor will do it automatically when you create a new row - this is the relevant code:

                if ( action === 'create' && idGet( toSave ) === undefined ) {
                    idSet( toSave, +new Date() +''+ key );
                }
    

    So you just need to not have the id field defined in the fields list (i.e. don't let the user input a value - Editor will assign one automatically).

    Is there a way to access the Editor's internal DataSet?

    rows().data() will give you the data from a DataTable.

    Allan

  • KostasRKostasR Posts: 24Questions: 5Answers: 0

    sorry Allan,
    i gets an error: "idGet is not defined"
    I used the website search but I did not find a description for idGet.

            editor.on( 'preSubmit', function ( e, data, action ) {
    
                if ( action === 'create' && idGet( toSave ) === undefined ) {
                    idSet( toSave, +new Date() +''+ key );
                }
            } );
    

    If I understand correctly, this code works when I start with an empty DataSet.
    My JSON array comes with some datasets as data source for DataTables.
    Is this variant better in this case?

            editor.on( 'preSubmit', function ( e, data, action ) {
    
                if ( action == 'create' ) {
    
                    $.each( data.data, function ( key, values ) {
                        var i = newID--;
                        data.data[ key ]['ID'] = i;
                        data.data[ i ] = data.data[key];
                        delete data.data[key];
                    } );
                }
            } );
    

    I think my case is closed.
    Thank you very much for your great support.

    You could take another example of how can be edited a simple array. That could be interesting for others too.

    Regards,
    Kostas

  • allanallan Posts: 61,950Questions: 1Answers: 10,158 Site admin

    Hi Kostas,

    The code I posted was internal code from Editor, just to show you the logic it uses. It isn't meant to be used externally.

    However, good to hear you've got it working the way you need now.

    Allan

This discussion has been closed.