.NET: Record vanishes from table after checkbox cell toggled; must be refreshed.

.NET: Record vanishes from table after checkbox cell toggled; must be refreshed.

rdmrdm Posts: 194Questions: 55Answers: 4
edited October 2017 in Editor

I am using the Always Shown Checkbox example.

When I toggle the checkbox, the new value correctly updates in the database. However, the record immediately vanishes and I need to manually refresh the page to bring the record back.

To resolve this symptom, I can add a "refresh" command somewhere, but I'm hoping it's as simple missing a critical command that wasn't in the example. Or maybe I'm falsely associating the symptom with the code I identified. What should I be doing differently to resolved this problem?

Here are what I think might be the two significant pieces of code.

In the jQuery script block:

// GOOD NEWS : data edit is correctly updated in database
// BAD NEWS : edited row immediately vanishes and page must be manually refreshed
$('#edittable').on( 'change', 'input.editor-active', function () {
        editor
            .edit($(this).closest('tr'),false)
            .set('Active', $(this).prop( 'checked' ) ? 1 : 0 )
            .submit();
    });

In the Controller:
(I had to make a tweak to the formatters to make them pass and accept the correct data values). Debug logs and webpage tests proved to me that the browser is showing and saving the correct values, except for that "edited row just vanishes" part.

using (var db = new DataTables.Database(settings.DbType, settings.DbMiaConnection))
{
    var response = new Editor(db, "MiaRoster2PartA", "Id")
        .Field(new Field("Campus"))
        .Field(new Field("StudentName"))
        .Field(new Field("StudentId"))
        .Field(new Field("CreditGoal"))
        .Field(new Field("Active")
            .GetFormatter((val, data) => val.ToString().ToLower() == "true" ? 1 : 0)
            .SetFormatter((val, data) => val.ToString() == "" ? 0 : 1)
        ).Where("Campus",campus);

    return Json(response.Process(formData).Data(), JsonRequestBehavior.AllowGet);
}

This question has accepted answers - jump to:

Answers

  • rdmrdm Posts: 194Questions: 55Answers: 4

    Still digging into this. Not sure why the record vanishes after editing. With all other inline pages I've set up (without use of the checkbox), the record never vanished after editing.

  • kthorngrenkthorngren Posts: 21,303Questions: 26Answers: 4,947
    edited October 2017

    I've seen this behavior happen if the returned (updated) data is not the same structure as when the table is built. I would start by validating the returned data with either the browser's developer tools or the debugger output.

    Kevin

  • rdmrdm Posts: 194Questions: 55Answers: 4

    I've looked on the Validation page, but I don't see anything resembling my scenario. For the sake of time, I'm adding a command to resubmit & refresh the page. Not a real solution,but I'm not able to see any culprit here, as the data being saved and shown is correct.

    $('#edittable').on('change',
        'input.editor-active',
        function() {
            editor.edit($(this).closest('tr'), false)
                             .set('Active', $(this).prop('checked') ? 1 : 0).submit();
    
            // refresh page
            $("#formSubmit").click();
        });
    
  • allanallan Posts: 63,471Questions: 1Answers: 10,467 Site admin

    As Kevin says, Editor will remove the row after an edit if the data being sent back from the server-side does not include the updated row's information.

    Can you show me the JSON that the server is returning after the submit of the Editor form happens?

    Allan

  • rdmrdm Posts: 194Questions: 55Answers: 4

    Thanks @allan --

    This the JSON from the Chrome Developer Tools. The fields and values look correct.

    {
        "draw": null,
        "data": [
            {
                "DT_RowId": "row_1",
                "Campus": "ABC",
                "StudentName": "Test Student A",
                "StudentId": "121834",
                "CreditGoal": "3",
                "Active": "0"
            },
            {
                "DT_RowId": "row_2",
                "Campus": "ABC",
                "StudentName": "Test Student B",
                "StudentId": "121792",
                "CreditGoal": "2",
                "Active": "1"
            },
            {
                "DT_RowId": "row_3",
                "Campus": "ABC",
                "StudentName": "Test Student C",
                "StudentId": "121432",
                "CreditGoal": "2",
                "Active": "1"
            }
        ],
        "recordsTotal": null,
        "recordsFiltered": null,
        "error": null,
        "fieldErrors": [ ],
        "id": null,
        "meta": { },
        "options": { },
        "files": { },
        "upload": {
            "id": null
        },
        "debugSql": null,
        "cancelled": [ ]
    }
    
  • rdmrdm Posts: 194Questions: 55Answers: 4

    To make this more transparent, I tried to find an online C# MVC and SQL Server fiddle. I haven't found one yet.

  • kthorngrenkthorngren Posts: 21,303Questions: 26Answers: 4,947

    Is the above the returned data from inline editing?

    It seems that only one row of data should be returned. If you monitor the "Ajax data" tab of the Always shown checkbox example it shows that only one row of data is returned immediately after checking or unchecking the checkbox.

    Kevin

  • rdmrdm Posts: 194Questions: 55Answers: 4

    @kthorngren -- Only the top record is the one that was edited. I was focusing on the fields and value in each field. I didn't consider that only the edited record would be returned.

  • kthorngrenkthorngren Posts: 21,303Questions: 26Answers: 4,947

    The expected return data is described in this doc:
    https://editor.datatables.net/manual/server#Edit

    Kevin

  • rdmrdm Posts: 194Questions: 55Answers: 4

    @kthorngren -- I backtracked a little bit and think I'm coming close to a solution. I rebuilt my entire code scenario from scratch and am able to verify that the JSON returns a single edited record after I toggle a checkbox.

    Having done this, I return to the problems I had in my very first iteration:
    * Edited data does not update in the database
    * When the page renders, the values in the database are not reflected in the table.

    Perhaps a problem is in the set formatter or in the get formatter I don't have. Still tinkering with this.

    This is the code I have now.

    Controller

    var response = new Editor(db, "MiaRoster2PartACopy", "Id")
        .Field(new Field("Campus"))
        .Field(new Field("StudentName"))
        .Field(new Field("StudentId"))
        .Field(new Field("CreditGoal"))
        .Field(new Field("Active")
            .SetFormatter((val, data) => val.ToString() == "" ? 0 : 1))
            .Where("Campus",campus);
    
    return Json(response.Process(formData).Data(), JsonRequestBehavior.AllowGet);
    

    jQuery

    rowCallback: function(row, data) {
        // Set the checked state of the checkbox in the table
        $('input.editor-active', row).prop( 'checked', data.Active === 1 );
    }
    
    $('#edittable').on('change',
        'input.editor-active',
        function() {
            editor
                .edit( $(this).closest('tr'), false )
                .set( 'Active', $(this).prop( 'checked' ) ? 1 : 0 )
                .submit();
            //$("#formSubmit").click();
        });
    
  • rdmrdm Posts: 194Questions: 55Answers: 4

    I'm getting a better handle on the Chrome Developer Tools.

    When I look at the header, I see that the correct record with the correct information is sent. (Sensitive info redacted.)

    Looking at the response, I see this, which looks to me like a null response.

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

    So I looked on the server side. I see that the formData variable contains the correct information. So the correct form data is arriving to the controller.

    I think in the end, the issue is in the controller, but I don't know what else to check.

    • The formData is correct.
    • The SetFormatter correctly persists data

    What else could I dig into?

    [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
            public ActionResult GetContentList(string campus)
            {
                var settings = Properties.Settings.Default;
                var formData = HttpContext.Request.Form;
    
                // formData appears to be correct
                //Debug.WriteLine($"formData:: {formData}");
                
                using (var db = new DataTables.Database(settings.DbType, settings.DbMiaConnection))
                {
                    var response = new Editor(db, "MiaRoster2PartACopy", "Id")
                        .Field(new Field("Campus"))
                        .Field(new Field("StudentName"))
                        .Field(new Field("StudentId"))
                        .Field(new Field("CreditGoal"))
                        .Field(new Field("Active")
                            .SetFormatter((val, data) => val.ToString() == "" ? 0 : 1))
                            .Where("Campus",campus);
    
                    return Json(response.Process(formData).Data(), JsonRequestBehavior.AllowGet);
                }
            }
    
  • allanallan Posts: 63,471Questions: 1Answers: 10,467 Site admin
    Answer ✓

    "data": [ ],

    Yes - this is missing the row that was edited.

    .Where("Campus",campus);

    What is campus? The where filter will also be applied to the data that was edited - so if you edit a row with data that makes it get filtered out, it wouldn't be returned, and thus should be removed from the display.

    Allan

  • rdmrdm Posts: 194Questions: 55Answers: 4

    That is the key.

    Campus is a value that is always sent by View's controller whenever the View renders.

    This poses a problem. While you're right -- taking out that Where() fragment solves the problem, I still need to filter by Campus at all times, whether it's the View rendering or when a record is edited.

    $('#edittable').DataTable({
        /* -- more code -- */
        ajax: {
            url: "@Url.Action("GetContentList")",
            data: {
                campus: "@Model.Campus"
            },
            type: "POST"
        },  
        /* -- more code -- */
    });
    

    Then the above is triggered (on page load, I believe), the .Where() has a value act on. When I edit the record, because Campus is not supplied as a parameter.

    So the trick might be in editing this .on('change') function, so that the Campus value that is in the row is known. It is currently marked as readonly because it needs to seen, but not changed.

    $('#edittable').on('change',
                    'input.editor-active',
                    function() {
                        editor
                            .edit($(this).closest('tr'), false)
                            .set('Active', $(this).prop('checked') ? 1 : 0)
                            .submit();
                    });
    
  • allanallan Posts: 63,471Questions: 1Answers: 10,467 Site admin
    Answer ✓

    Use ajax.data (Editor) in a similar way as you have for DataTables:

        ajax: {
            url: "@Url.Action("GetContentList")",
            data: function ( d ) {
                d.campus = "@Model.Campus"';
            },
    

    Allan

  • rdmrdm Posts: 194Questions: 55Answers: 4

    Sorry @Allan -- I mean to click that it did answer the question. The thing to remember is to not place a where statement in the controller.

  • allanallan Posts: 63,471Questions: 1Answers: 10,467 Site admin

    No problem - marked as answered now.

    Allan

This discussion has been closed.