Inline edit generates error : TypeError: Cannot read properties of undefined (reading 'attach')

Inline edit generates error : TypeError: Cannot read properties of undefined (reading 'attach')

MarkAndersonUKMarkAndersonUK Posts: 43Questions: 16Answers: 0

Hi,

I am seeing a Javascript error appearing every time an inline edit saves a record. This error does NOT appear when I use the full edit method.

The error is :

Uncaught TypeError: Cannot read properties of undefined (reading 'attach')
at Editor.inline (dataTables.editor.js:2713)

I am running Editor v2.06 using the NodeJS ServerSide libraries.

I have tried everything I can think of, including stripping down the edit to a basic single table with no joins.

Here is the test config:

NodeJS HTML Page (Jade/Pug format):

    extends layout
    block content
        .box.mr-5.ml-3.mt-5
            table#clients.display.compact(cellpadding='0' cellspacing='0' border='0' width='100%')
                thead
                    tr
                        th.small CPN
                        th.small IS
                        th.small First
                        th.small Middle
                        th.small Last
                        th.small EMail1
                        th.small EMail2
                        th.small State
                        th.small Zip
                        th.small Phone 1
                        th.small Phone 2
                        th.small NPN
                        th.small notes

    block append footer

        script(type='text/javascript').
            (function ($) {

                $(document).ready(function () {
                    var recruitEditor = new $.fn.dataTable.Editor({
                        ajax: '/Recruits1/api/clients',
                        table: '#clients',
                        fields: [
                            {label: "CPN ID:", name: "clients.Id"},
                            {label: "InfusionSoft ID:", name: "clients.infusionsoft_id"},
                            {label: "First Name:", name: "clients.FirstName"},
                            {label: "Middle Name:", name: "clients.MiddleName"},
                            {label: "Last Name:", name: "clients.LastName"},
                            {label: "Suffix:", name: "clients.Suffix"},
                            {label: "EMail1:", name: "clients.EMail1"},
                            {label: "EMail2:", name: "clients.EMail2"},
                            {label: "State (Home):", name: "clients.HomeState"},
                            {label: "ZipCode (Home):", name: "clients.HomeZipCode"},
                            {label: "Phone 1:", name: "clients.Phone1Number"},
                            {label: "Phone 2:", name: "clients.Phone2Number"},
                            {label: "NPN:", name: "clients.NPN"},
                            {label: "Notes:", name: "clients.Notes"}
                        ]
                    });


                    $('#clients').on( 'click', 'tbody td:not(:first-child,.bbledit)', function (e) {
                        recruitEditor.inline(this, {
                            onBlur: 'submit'
                        });
                    });        

                    var recruit_table = $('#clients').DataTable({
                        dom: 'lfrtip',
                        ajax: {
                            url: '/Recruits1/api/clients',
                            type: "POST"
                        },
                        serverSide: true,
                        processing: false,
                        columns: [
                            {data: "clients.Id", class: "small"},
                            {data: "clients.infusionsoft_id", class: "small"},
                            {data: "clients.FirstName", class: "small"},
                            {data: "clients.MiddleName", class: "small"},
                            {data: "clients.LastName", class: "small"},
                            {data: "clients.EMail1", class: "small"},
                            {data: "clients.EMail2", class: "small"},
                            {data: "clients.HomeState", class: "small"},
                            {data: "clients.HomeZipCode", class: "small"},
                            {data: "clients.Phone1Number", class: "small"},
                            {data: "clients.Phone2Number", class: "small"},
                            {data: "clients.NPN", class: "small"},
                            {data: "clients.Notes", class: "small"}
                        ],     
                        select: true,
                    });
                });
            }(jQuery));

NodeJS Javascript:
const router = require('express').Router();
const expressValidator = require('express-validator');
const middleware = require('./middleware.js');

let ot198 = require('../ot198');
let {
    Editor,
    Field,
    Validate,
    Format,
    Options,
} = require("datatables.net-editor-server");


//All routes from /LifeCases are routed here.
router.get("/", middleware.loggedIn(), (req,res) => {
    res.render('recruits1', {showAdmin: true})
});

router.all('/api/clients', async function(req, res) {
    let editor = new Editor(ot198, 'clients', 'clients.Id')
        .fields(
            new Field("clients.Id"),
            new Field("clients.infusionsoft_id"),
            new Field("clients.AgentId"),
            new Field("clients.FirstName"),
            new Field("clients.MiddleName"),
            new Field("clients.LastName"),
            new Field("clients.Suffix"),
            new Field("clients.EMail1"),
            new Field("clients.EMail2"),
            new Field("clients.HomeState"),
            new Field("clients.HomeZipCode"),
            new Field("clients.Phone1Number"),
            new Field("clients.Phone2Number"),
            new Field("clients.Notes"),
            new Field("clients.NPN")
        )

        .where(function() {
            this.where('clients.isRecruitmentRec',  '1')
        })

    await editor.process(req.body);
    res.json(editor.data());
});

module.exports = router;

Any help or ideas would be appreciated.

**Note: ** the full table names were used throughout on purpose, as there is normally several joins in this
setup, but I removed them to simplify the code and to ensure they were not causing the issue.

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 61,723Questions: 1Answers: 10,108 Site admin
    Answer ✓

    Could you change:

    recruitEditor.inline(this, {
    

    to be:

    recruitEditor.inline(recruit_table.cell(this).index(), {
    

    please?

    The issue is that you have server-side processing enabled, so when the previous value is submitted the table will redraw, resulting in new DOM elements being created for the table contents. That means that this, while it is a td element, it isn't any longer the one which is actually displayed!

    Using the cell index addresses that. You can see that in our server-side processing inline editing example here.

    Allan

  • MarkAndersonUKMarkAndersonUK Posts: 43Questions: 16Answers: 0

    THanks @allan,

    Once again you guys rock, you hit the nail on the head. Will using the cell index also be required when using server-sided and the bubble editor ?

  • allanallan Posts: 61,723Questions: 1Answers: 10,108 Site admin

    Yes, for basically the same reason. It is something I might abstract out in future as you aren't the first to trip over this... :)

    Allan

Sign In or Register to comment.