Child Editor does not update after child edit

Child Editor does not update after child edit

dpanscikdpanscik Posts: 201Questions: 46Answers: 0

I am using a editor made by editor generator and adding in a child editor as per instructions here;
https://datatables.net/blog/2019/parent-child-editing-in-child-rows#DataTable-configuration

and with the final assembly example here;
https://datatables.net/media/blog/2019-01-11/edit.js

When I edit a row in a child table, and click "Update" the row disappears.

Step #1 - To recreate this issue select a row in a child table and click "EDIT"

Step #2 - Perform an edit and click "UPDATE"

Step #3 - Notice the row in the child table dissapears

Step #4 - Refreshing the browser tab, brings the child table row back (now edited)

This function is never getting triggered. Even though its a clone of the code in the instructions (1st link above) and placed in the exact same spot as the code for the assembly example (2nd link above).

        childEditor.on('submitSuccess', function () {
            console.log =("submit success triggered")
            childTable.rows().every(function () {
                if (this.child.isShown()) {
                    updateChild(this);
                }
            });
        });

Here is all the code together.;




/* * Editor client script for DB table GR_AlternativeBilling * Created by http://editor.datatables.net/generator */ addEventListener("DOMContentLoaded", function () { function createChild(row, data) { // This is the table we'll convert into a DataTable //var table = $('<table class="display childGrid" width="100%"/>'); var table = $('<table class="display childGrid" width="100%"/>'); // Display it the child row row.child(table).show(); var childEditor = new $.fn.dataTable.Editor({ ajax: { url: '/AlternativeBilling/DataTransport_Notes', data: function (d) { d.site = row.TableID; } }, table: table, fields: [{ label: "NoteType:", name: "NoteType" }, { label: "Note:", name: "Note" }, { label: "EditedBy", name: "EditedBy" }, { label: "EditedDate", name: "EditedDate" } ], select: true, processing: true, }); // Initialise as a DataTable var childTable = table.DataTable({ "orderCellsTop": true, "processing": true, // for show progress bar "language": { "processing": '<span class="sr-only h1" >Loading...</span> ' }, "filter": false, // this is for disable filter (search box) "orderMulti": false, // for disable multiple column at once "pageLength": 25, "lengthChange": true, "search": { "caseInsensitive": true }, "responsive": false, //for automatic child tables ajax: '/AlternativeBilling/DataTransport_Notes?TableName=AlternativeBilling&TableID=' + data.TableID, columns: [ { "data": "NoteType", "title": "Note Type", }, { "data": "Note", "title": "Note", }, { "data": "EditedBy", "title": "Edited By", }, { "data": "EditedDate", "title": "Edit Date", }, ], layout: { topStart: { buttons: [ { extend: 'create', editor: childEditor }, { extend: 'edit', editor: childEditor }, { extend: 'remove', editor: childEditor } ] } }, select: true, processing: true, }); childEditor.on('submitSuccess', function () { console.log =("submit success triggered") childTable.rows().every(function () { if (this.child.isShown()) { updateChild(this); } }); }); } var editor = new DataTable.Editor({ ajax: '/AlternativeBilling/DataTransport', table: '#GR_AlternativeBilling', fields: [ { "label": "Patient Name", "name": "PatientName" }, { "label": "Insurance:", "name": "Insurance" }, { "label": "Employer:", "name": "Employer" }, { "label": "Contact Name:", "name": "ContactName" }, { "label": "Contact Phone:", "name": "ContactPhone" }, { "label": "Contact Email:", "name": "ContactEmail" }, { "label": "Method:", "name": "Method" }, { "label": "Number Of Visits:", "name": "NumberOfVisits" } ] }); var mainTable = new DataTable('#GR_AlternativeBilling', { "search": { "caseInsensitive": true }, "serverSide": true, ajax: { "url": "/AlternativeBilling/DataTransport", "type": "POST", "datatype": "json", }, columns: [ { "data": "PatientName" }, { "data": "Insurance" }, { "data": "Employer" }, { "data": "ContactName" }, { "data": "ContactPhone" }, { "data": "ContactEmail" }, { "data": "Method" }, { "data": "NumberOfVisits" }, { className: 'details-control dt-control', orderable: false, data: null, defaultContent: '', width: '10%' }, ], layout: { topStart: { buttons: [ { extend: 'create', editor: editor }, { extend: 'edit', editor: editor }, { extend: 'remove', editor: editor } ] } }, select: true, processing: true, }); // Activate an inline edit on click of a table cell mainTable.on('click', '> tbody > td:not(:last-child)', function (e) { editor.inline(this); }); $('#GR_AlternativeBilling tbody').on('click', 'td.details-control', function () { var tr = $(this).closest('tr'); var row = mainTable.row(tr); if (row.child.isShown()) { // This row is already open - close it destroyChild(row); tr.removeClass('shown'); } else { // Open this row //format(row.data()); createChild(row, row.data()); tr.addClass('shown'); } }); function updateChild(row) { $("table", row.child()) .DataTable() .ajax.reload(); } function destroyChild(row) { var table = $("table", row.child()); table.detach(); table.DataTable().destroy(); // And then hide the row row.child.hide(); } function updateChild(row) { $('table', row.child()).DataTable().ajax.reload(); } });

Answers

  • kthorngrenkthorngren Posts: 20,991Questions: 26Answers: 4,887

    I would start by using the browser's network inspector to see the values sent in the XHR request and the JSON response when clicking the Update button in the child table. Please post both in the thread.

    Also look for errors in the browser's console. Let us know what you find.

    Kevin

  • dpanscikdpanscik Posts: 201Questions: 46Answers: 0

    There are no console errors.

    Here is the Post heading from the browser out to the server

    w_1%5D%5BNoteType%5D: Invoice
    data%5Brow_1%5D%5BNote%5D: this+is+a+note+AFTER+editing2345
    data%5Brow_1%5D%5BEditedBy%5D: 
    data%5Brow_1%5D%5BEditedDate%5D: 
    action: edit
    

    Here is the response

    {
        "draw": null,
        "data": [],
        "recordsTotal": null,
        "recordsFiltered": null,
        "error": null,
        "fieldErrors": [],
        "id": null,
        "meta": {},
        "options": {},
        "searchBuilder": {
            "options": {}
        },
        "searchPanes": {
            "options": {}
        },
        "files": {},
        "upload": {
            "id": null
        },
        "debug": null,
        "cancelled": []
    }
    

    Here is my controller. Pretty much stock editor generator .

            [Route("AlternativeBilling/DataTransport_Notes")]
            [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
            public ActionResult DataTransport_Notes(string TableName = null, string TableID = null)
            {
                DefaultConnection1 dbConnection2 = new DefaultConnection1();
    
                //var request = HttpContext.Current.Request;
                var request = System.Web.HttpContext.Current.Request.Form;
    
                var settings = Properties.Settings.Default;
    
                var Request = System.Web.HttpContext.Current.Request.Form;
    
                var value1 = Request["action"];
    
                //active DB update
                using (var db = new Database(settings.DbType, settings.DbConnection))
                {
    
                    var response = new Editor(db, "GR_Notes", "TableID")
                        .Model<GR_Notes>()
                        .Where("ForTableID", TableID, "=")
                        .Where("ForTableName", TableName, "=")
                        .TryCatch(false)
                        .Process(request)
                        .Data();
    
                    return Json(response, JsonRequestBehavior.AllowGet);
                }
            }
    
  • kthorngrenkthorngren Posts: 20,991Questions: 26Answers: 4,887

    I updated your post data to make it more readable by replacing %5B with [ and %5D with ]:

    w_1][NoteType]: Invoice
    data[row_1][Note]: this+is+a+note+AFTER+editing2345
    data[row_1][EditedBy]:
    data[row_1][EditedDate]:
    action: edit
    

    Looks like you might be missing some info. I suspect there is another parameter called site from the Editor's ajax request:

                ajax: {
                    url: '/AlternativeBilling/DataTransport_Notes',
                    data: function (d) {
                        d.site = row.TableID;
                    }
                },
    

    I'm not familiar with PHP nor what the Generator builds but it seems your code is looking for

    TableID and TableName which neither are sent in the request. Possibly you need to change d.site = row.TableID; to d.TableID = row.TableID;. You might need to add another parameter for TableName or remove it from the where condition. See this section of the blog you link to.

    Kevin

  • dpanscikdpanscik Posts: 201Questions: 46Answers: 0
    edited July 21

    d.site is the name of one of the parent table in the official example. I think this needs to be the name of my parent table.

    I believe for me the value should have been d.GR_AlternativeBilling

    I made the change from d.site to d.GR_AlternativeBilling

    I also noticed i was missing var rowData = row.data(); on top of my child editor declaration.

    With both changes in play, there is no difference for this particular issue.

    Here is the new child editor declaration.

            var rowData = row.data();
            var childEditor = new $.fn.dataTable.Editor({
                ajax: {
                    url: '/AlternativeBilling/DataTransport_Notes',
                    data: function (d) {
                        d.GR_AlternativeBilling = rowData.TableID;
                    }
                },
                table: table,
                fields: [{
                    label: "NoteType:",
                    name: "NoteType"
                }, {
                    label: "Note:",
                    name: "Note"
                }, {
                    label: "EditedBy",
                    name: "EditedBy"
                }, {
                    label: "EditedDate",
                    name: "EditedDate"
                }
                ],
    
                select: true,
                processing: true,
            });
    
  • dpanscikdpanscik Posts: 201Questions: 46Answers: 0

    Ive just made some headway. Ill have a new update shortly.

  • kthorngrenkthorngren Posts: 20,991Questions: 26Answers: 4,887
    edited July 21

    I think that if you put “.debug()” before “process()” in the child query you will see the query string used in the JSON response. I don’t believe the where clause is created correctly because you aren’t matching it the parameters sent with the variables used in the query. I could be wrong as I no very little about PHP but I don’t see where you are passing “TableID” from the client.

    Kevin

  • dpanscikdpanscik Posts: 201Questions: 46Answers: 0

    Ok. Here is the update. I cleaned up the issues that Kevin mentioned where the DB field "ForDataTable" and "ForTableID" was not getting populated on a CREATE or EDIT function.

    However I still am having an issue of the newly created data (and) edited data not showing up in the child table unless I do a browser refresh.

    What I did to solve this problem the problem that Kevin identified is grab the form data in the controller and modify it to work for my scenario.

    this is the form data modification.

                var propInfo = collection.GetType().GetProperty("IsReadOnly", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                propInfo.SetValue(collection, false, new object[] { });
    
                if (collection["action"] == "create")
                {
                    collection["data[0][ForTableID]"] = collection["ForTableID"];
                    collection.Remove("data[0][EditedBy]");
                    collection.Add("data[0][EditedBy]", User.Identity.Name);
                    collection.Add("data[0][ForTableName]", "AlternativeBilling");
                }
                if (collection["action"] == "edit")
                {
                    collection["data[0][ForTableID]"] = collection["ForTableID"];
                    collection.Remove("data[0][EditedBy]");
                    collection.Add("data[0][EditedBy]", User.Identity.Name);
                    collection.Add("data[0][ForTableName]", "AlternativeBilling");
                }
                if (collection["action"] == "delete")
                {
                }
    

    and here is my whole controller

        public class AlternativeBillingController : Controller
        {
            [Route("AlternativeBilling/DataTransport")]
            [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
            public ActionResult DataTransport(FormCollection form_id)
            {
                
                //var request = HttpContext.Current.Request;
                var request = System.Web.HttpContext.Current.Request.Form;
    
                var settings = Properties.Settings.Default;
    
    
    
                using (var db = new Database(settings.DbType, settings.DbConnection))
                {
    
                    var response = new Editor(db, "GR_AlternativeBilling", "TableID")
                        .Model<GR_AlternativeBilling>()
                        .TryCatch(false)
                        .Process(request)
                        .Data();
    
                    return Json(response, JsonRequestBehavior.AllowGet);
                }
            }
    
            [Route("AlternativeBilling/DataTransport_Notes")]
            [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
            public ActionResult DataTransport_Notes(string TableName = null, string TableID = null)
            {
                var collection = System.Web.HttpContext.Current.Request.Form;
    
                var settings = Properties.Settings.Default;
    
                var propInfo = collection.GetType().GetProperty("IsReadOnly", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                propInfo.SetValue(collection, false, new object[] { });
    
                if (collection["action"] == "create")
                {
                    collection["data[0][ForTableID]"] = collection["ForTableID"];
                    collection.Remove("data[0][EditedBy]");
                    collection.Add("data[0][EditedBy]", User.Identity.Name);
                    collection.Add("data[0][ForTableName]", "AlternativeBilling");
                }
                if (collection["action"] == "edit")
                {
                    collection["data[0][ForTableID]"] = collection["ForTableID"];
                    collection.Remove("data[0][EditedBy]");
                    collection.Add("data[0][EditedBy]", User.Identity.Name);
                    collection.Add("data[0][ForTableName]", "AlternativeBilling");
                }
                if (collection["action"] == "delete")
                {
                }
                    
    
                //active DB update
                using (var db = new Database(settings.DbType, settings.DbConnection))
                {
    
                    var response = new Editor(db, "GR_Notes", "TableID")
                        .Model<GR_Notes>()
                        .Where("ForTableID", TableID, "=")
                        .Where("ForTableName", TableName, "=")
                        .TryCatch(false)
                        .Process(collection)
                        .Data();
    
                    return Json(response, JsonRequestBehavior.AllowGet);
                }
            }
        }
    
  • allanallan Posts: 62,858Questions: 1Answers: 10,344 Site admin

    To check my understanding - you issue an edit or insert command from the client-side to the server (i.e. submit the child form), but then the table isn't updated with the new data. Correct?

    That will mean that the server-side is not responding with the data expected. Likely the data returned is just an empty array is my guess. Can you show us the JSON data for an insert response (and perhaps also the data for what is submitted for that request)?

    d.GR_AlternativeBilling = rowData.TableID;

    "GR_AlternativeBilling" is the table name in the code above. I also don't see that variable being used anywhere.

    If you consider the blog post, you'll see the PHP controller for the child table has:

    ->where( 'site', $_POST['site'] )
    

    The C# package has the same example, where the equivalent is:

    .Where("site", site)
    

    With site being defined in the controller parameters:

    public ActionResult Users([FromForm]string site="-1")
    

    That is the linking value, so that is fundamentally important for the parent / child relationship to operate. I don't see a left join in the code above, so I'm not sure what the linking field name is?

    Allan

  • dpanscikdpanscik Posts: 201Questions: 46Answers: 0

    Hi Allan,

    Thats not quite what is happening. The data is indeed making it to the database, but the child table is not refreshing after a edit/insert.

    Ill send you a PM with a dropbox link to a video to give you a visual of what is happening.

  • dpanscikdpanscik Posts: 201Questions: 46Answers: 0

    This is resolved. Allan was on the right track. The DataTable was passing important details by way of URL parameter but the editor was not.

    By incorporating the child editor, I have learned quite allot about how datables works that was not obvious to myself when just doing a parent editor with no child editor.

  • allanallan Posts: 62,858Questions: 1Answers: 10,344 Site admin

    Awesome - thanks for the update and great to hear you've got it working now!

    Allan

Sign In or Register to comment.