Issue with Whole Row Inline Editing: onBlur: 'submit' + submit: 'allIfChanged'

Issue with Whole Row Inline Editing: onBlur: 'submit' + submit: 'allIfChanged'

YousefMohammadYousefMohammad Posts: 3Questions: 1Answers: 0

Link to test case:
Debugger code (debug.datatables.net):
Error messages shown:
Description of problem:
I'm trying to implement whole row inline editing using DataTables Editor(https://editor.datatables.net/examples/inline-editing/fullRowCells.html), where clicking any cell in a row activates inline editing for the entire row. I'm using the following configuration:
onBlur: 'submit',
submit: 'allIfChanged'
Issues I'm encountering:
JavaScript error when switching rows:
When I click from one row to another (using the mouse), I get the following error in the console:
Uncaught TypeError: Cannot read properties of undefined (reading 'attach')
at R.Rt [as inline] (dataTables.editor.min.do2v40wa48.js:6:25488)
...

Unnecessary submission:
Even when no changes are made to the row, the editor still submits the data. I expected submit: 'allIfChanged' to prevent submission if nothing was modified.

My DataTable uses ajax for both data retrieval and editing,ajax is configured on datatable and editor for edit .
Both endpoints are configured to use POST.

Is there a recommended way to avoid this error when switching rows and to prevent submission when no changes are made?

This question has accepted answers - jump to:

Answers

  • kthorngrenkthorngren Posts: 22,124Questions: 26Answers: 5,097

    Uncaught TypeError: Cannot read properties of undefined (reading 'attach')

    Without more information it's hard to guess what the problem might be. There are some threads on the forum with the same error. Maybe they will help with the error. For example:

    https://datatables.net/forums/discussion/71465/inline-edit-generates-error-typeerror-cannot-read-properties-of-undefined-reading-attach
    https://datatables.net/forums/discussion/70256/inline-editor-for-whole-row-does-not-work
    https://datatables.net/forums/discussion/74243/inline-editor-onblur-submit-give-error-if-clicked-any-other-editable-field-in-datatable

    If you are using server side processing see this example to learn how to use inline editing with server side processing.

    I expected submit: 'allIfChanged' to prevent submission if nothing was modified.

    Again it will be difficult to troubleshoot without seeing the issue. There are some troubleshooting steps in this thread. Try those and let use know the results.

    At a minimum please post your full Editor and Datatables ini code and the code used for inline editing. Better is a link to your page or a test case replicating the issues. If you can't post the links publicly you might be able to make private arrangements with Allan via PM for direct access.

    Kevin

  • YousefMohammadYousefMohammad Posts: 3Questions: 1Answers: 0
    edited July 6

    adding code :

     var editor = new DataTable.Editor({
        ajax: '/api/staff',
        fields: [
            {
                label: 'First name:',
                name: 'first_name'
            },
            {
                label: 'Last name:',
                name: 'last_name'
            },
            {
                label: 'Position:',
                name: 'position'
            },
            {
                label: 'Office:',
                name: 'office'
            },
            {
                label: 'Extension:',
                name: 'extn'
            },
            {
                label: 'Start date:',
                name: 'start_date',
                type: 'datetime'
            },
            {
                label: 'Salary:',
                name: 'salary'
            }
        ],
        table: '#example'
    });
    
    var table = $('#example').DataTable({
        ajax: {
            url: '/api/staff',
            type: 'POST'
        },
        columns: [
            {
                data: null,
                orderable: false,
                render: DataTable.render.select(),
                searchable: false
            },
            { data: 'first_name' },
            { data: 'last_name' },
            { data: 'position' },
            { data: 'office' },
            { data: 'start_date' },
            { data: 'salary', render: DataTable.render.number(null, null, 0, '$') }
        ],
        layout: {
            topStart: {
                buttons: [
                    { extend: 'create', editor: editor },
                    { extend: 'edit', editor: editor },
                    { extend: 'remove', editor: editor }
                ]
            }
        },
        order: [[1, 'asc']],
        select: {
            selector: 'td:first-child',
            style: 'os'
        },
        serverSide: true,
        processing: true,
    });
    
    // Activate an inline edit on click of a table cell
    $('#example').on('click', 'tbody td:not(:first-child)', function (e) {
        editor.inline(table.cells(this.parentNode, '*').nodes(), {
            onBlur: 'submit',
            submit: 'allIfChanged'
        });
    });
    

    Edited by Kevin: Syntax highlighting. Details on how to highlight code using markdown can be found in this guide

  • YousefMohammadYousefMohammad Posts: 3Questions: 1Answers: 0

    Hi Kevin

    Actually i used the code in this example (https://editor.datatables.net/examples/inline-editing/serverSide.html) with 2 changes:
    1- add processing:true option to datatable options
    2-replace:

    $('#example').on('click', 'tbody td:not(:first-child)', function (e) {
        editor.inline(table.cell(this).index(), {
            onBlur: 'submit'
        });
    });
    

    with:

    $('#example').on('click', 'tbody td:not(:first-child)', function (e) {
        editor.inline(table.cells(this.parentNode, '*').nodes(), {
            onBlur: 'submit',
            submit: 'allIfChanged'
        });
    });   
    

    I checked forums links but i didn't find how to use index() with row

  • kthorngrenkthorngren Posts: 22,124Questions: 26Answers: 5,097
    edited July 6

    The real problem is the timing of updating the edited row and the use of the td click event when clicking on another row. When this sequence occurs with server side processing the edited row is updated then there is a table draw, fetching the page from the server, to update the display. This removes the row clicked on after the edits then rewrites the HTML table the the response.

    I don't know the best way to handle this. The below code snippet will demonstrate:

    var table = $('#example').DataTable();
    editor = table.editor();
    // Turn off original click event handler for inline editing
    table.off('click', 'tbody td:not(:first-child)');
    
    // Activate an inline edit on click of a table cell
    $('#example').on('click', 'tbody td:not(:first-child)', function (e) {
        var row = table.row( this.parentNode ).index();
    
        setTimeout(() => {
            editor.inline(table.cells( row, '*' ).nodes(), {
                onBlur: 'submit',
                submit: 'allIfChanged'
            });
        }, 500);  // delay to allow HTML table to be updated
    });
    

    Paste this into the console of the server side processing example. The first four lines are only to set up the environment for the click event to work. The click event gets the row().index() to pass into the inline edit function. Which is executed after a 500 ms delay. You can make this delay smaller to see the affect.

    @allan might have a better more reliable option.

    I expected submit: 'allIfChanged' to prevent submission if nothing was modified.

    This example also shows that allIfChanged works properly as there are no other changes in the row when none of the cells are changed. You can verify that unchanged data does submit the row by using the browser's network inspector. Try the troubleshooting steps found in the thread I linked to earlier to start the debugging process.

    Kevin

  • allanallan Posts: 64,688Questions: 1Answers: 10,697 Site admin
    Answer ✓

    Regarding allIfChanged first - normally an unexpected submission is caused by data changing type. For example if salary is an integer in the loaded data, when it is read back from the document it must be a string (since all input values are string). fields.type can help to address that if that is the issue.

    With the timing issue and the nodes - normally with inline editing the solution is to pass in the cell index (e.g. this example), that way we aren't using the Element as the reference (since it will be replaced on each draw and no longer have any relevance).

    It hasn't actually occurred to me before to try full row editing with server-side processing (sorry - it probably should have - so many options!), but you could try the same thing, just with the plural - e.g.:

    editor.inline(table.cells( row, '*' ).indexes(), {
    

    Allan

  • kthorngrenkthorngren Posts: 22,124Questions: 26Answers: 5,097
    Answer ✓

    Cool, I just tried that by copying this code into that example and it does work:

    var table = $('#example').DataTable();
    editor = table.editor();
    // Turn off original click event handler for inline editing
    table.off('click', 'tbody td:not(:first-child)');
    
    // Activate an inline edit on click of a table cell
    $('#example').on('click', 'tbody td:not(:first-child)', function (e) {
        var row = table.row( this.parentNode ).index();
    
        editor.inline(table.cells( row, '*').indexes(), {
            onBlur: 'submit',
            submit: 'allIfChanged'
        });
    });
    

    Kevin

  • allanallan Posts: 64,688Questions: 1Answers: 10,697 Site admin

    Nice one - many thanks for trying that Kevin!

    Allan

Sign In or Register to comment.