Editor Buttons Not Sending AJAX Requests?

Editor Buttons Not Sending AJAX Requests?

SnacklesSnackles Posts: 33Questions: 8Answers: 0

Hi all,

I'm pretty new to web app development and am kind of struggling with getting the Editor buttons to create, edit, or delete. I'm testing around with an ASP.NET app and followed a tutorial online that showed how to get CRUD operations working without the use of Editor, but I'm not a fan of the format.

It uses a single Create new record button at the top of the table and an "Edit" and "Delete" -- I think hyperlink? -- in the far right columns of the table and I'd prefer to have three buttons at the top of the table that can perform those functions. Using this method I can see the AJAX requests going through in my Chrome developer tools, but when I try to use the DataTables Editor buttons to do the same thing, no requests are made.

I assumed it'd be as easy as figuring out how to assign the current working functions assigned to the inline buttons to the DataTables Editor buttons, but I can't seem to.

This is my code. I'm not entirely sure how to use JSFiddle at the moment, but I can try if it'll help more to see the code run.

This question has an accepted answers - jump to answer

Answers

  • SnacklesSnackles Posts: 33Questions: 8Answers: 0

    HomeController.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Helpers;
    using System.Web.Mvc;
    using Test2.Models;
    
    namespace Test2.Controllers
    {
        public class HomeController : Controller
        {
            // GET: Home
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult GetEmployees() {
                using (TestEntities dc = new TestEntities())
                {
                    var employees = dc.Employees.OrderBy(a => a.FirstName).ToList();
                    return Json(new { data = employees }, JsonRequestBehavior.AllowGet);
                }
            }
    
            [HttpGet]
            public ActionResult Save(int id)
            {
                using (TestEntities dc = new TestEntities())
                {
                    var v = dc.Employees.Where(a => a.EmployeeID == id).FirstOrDefault();
                    return View(v);
                }
            }
    
            [HttpPost]
            public ActionResult Save(Employee emp)
            {
                bool status = false;
                if (ModelState.IsValid)
                {
                    using (TestEntities dc = new TestEntities())
                    {
                        if(emp.EmployeeID > 0)
                        {
                            //Edit
                            var v = dc.Employees.Where(a => a.EmployeeID == emp.EmployeeID).FirstOrDefault();
                            if(v != null)
                            {
                                v.FirstName = emp.FirstName;
                                v.LastName = emp.LastName;
                                v.City = emp.City;
                                v.Country = emp.Country;
                            }
                        }
                        else
                        {
                            //Save
                            dc.Employees.Add(emp);
                        }
                        dc.SaveChanges();
                        status = true;
                    }
                }
                return new JsonResult { Data = new { status = status } };
            }
    
            [HttpGet]
            public ActionResult Delete(int id)
            {
                using (TestEntities dc = new TestEntities())
                {
                    var v = dc.Employees.Where(a => a.EmployeeID == id).FirstOrDefault();
                    if (v != null)
                    {
                        return View(v);
                    }
                    else
                    {
                        return HttpNotFound();
                    }
                }
            }
    
            [HttpPost]
            [ActionName("Delete")]
            public ActionResult DeleteEmployee(int id)
            {
                bool status = false;
                using (TestEntities dc = new TestEntities())
                {
                    var v = dc.Employees.Where(a => a.EmployeeID == id).FirstOrDefault();
                    if (v!= null)
                    {
                        dc.Employees.Remove(v);
                        dc.SaveChanges();
                        status = true;
                    }
                }
                return new JsonResult { Data = new { status = status } };
            }
        }
    }
    
  • SnacklesSnackles Posts: 33Questions: 8Answers: 0

    Index.cshtml:

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <script src="~/Scripts/jquery-3.3.1.min.js"></script>
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    <script src="~/Scripts/jquery-ui-1.12.1.min.js"></script>
    
    <script type="text/javascript" charset="utf-8" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdn.datatables.net/buttons/1.5.4/js/dataTables.buttons.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.flash.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.html5.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.print.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdn.datatables.net/select/1.2.7/js/dataTables.select.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdn.datatables.net/responsive/1.0.7/js/dataTables.responsive.min.js"></script>
    <script src="~/Editor-1.8.1/js/dataTables.editor.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.4/moment.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="https://cdn.datatables.net/plug-ins/1.10.19/sorting/datetime-moment.js"></script>
    
    <style>
        span.field-validation-error {
            color: red;
        }
    </style>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <link src="~/Editor-1.8.1/css/editor.dataTables.min.css" />
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
        <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" />
        <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/1.5.4/css/buttons.dataTables.min.css" />
        <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.2.7/css/select.dataTables.min.css" />
        <link rel="stylesheet" type="text/css" href="https://editor.datatables.net/extensions/Editor/css/editor.dataTables.min.css" />
        <link href="~/Content/themes/base/jquery-ui.min.css" rel="stylesheet" />
        </head>
    
    <body>
        <div style="width:90%; margin:0 auto" class="tablecontainer">
            <a class="popup btn btn-primary" href="/home/save/0" style="margin-bottom:20px; margin-top:20px;">Add New Employee</a>
            <table id="myDatatable">
                <thead>
                    <tr>
                        <th>First Name</th>
                        <th>Last Name</th>
                        <th>Email ID</th>
                        <th>City</th>
                        <th>Country</th>
                        <th>Edit</th>
                        <th>Delete</th>
                    </tr>
                </thead>
            </table>
        </div>
    
        <script>
    
            var editor;
    
            $(document).ready(function () {
    
                editor = new $.fn.dataTable.Editor({
                    table: "#myDatatable",
                    idSrc: 'EmployeeID',
                    fields: [{
                        label: "First Name:",
                        name: "FirstName"
                    }, {
                        label: "Last Name:",
                        name: "LastName"
                    }, {
                        label: "Email:",
                        name: "EmailID"
                    }, {
                        label: "City:",
                        name: "City"
                    }, {
                        label: "Country:",
                        name: "Country"
                    }]
                });
    
                // Activate an inline edit on click of a table cell
                // Activate an inline edit on click of a table cell
                $('#myDatatable').on('click', 'tbody td:not(:first-child)', function (e) {
                    editor.inline(this, {
                        buttons: { label: '&gt;', fn: function () { this.submit(); } }
                    });
                });
    
                var oTable = $('#myDatatable').DataTable({
                    "ajax": {
                        "url": '/home/GetEmployees',
                        "type": "get",
                        "datatype": "json"
                    },
                    responsive: true,
                    "columns": [
                        { "data": "FirstName", "autoWidth": "true" },
                        { "data": "LastName", "autoWidth": "true" },
                        { "data": "EmailID", "autoWidth": "true" },
                        { "data": "City", "autoWidth": "true" },
                        { "data": "Country", "autoWidth": "true" },
                        {
                            "data": "EmployeeID", "width": "50px", "render": function (data) {
                                return '<a class="popup" href="/home/save/' + data + '">Edit</a>';
                            }
                        },
                        {
                            "data": "EmployeeID", "width": "50px", "render": function (data) {
                                return '<a class="popup" href="/home/delete/' + data + '">Delete</a>';
                            }
                        }
                    ],
                    select: true,
                    dom: '<"floatRight"B><"clear">lfrtip',
                    buttons: [
                        { extend: "create", editor: editor },
                        { extend: "edit", editor: editor },
                        { extend: "remove", editor: editor }
                    ]
                });
                
                $('.tablecontainer').on('click', 'a.popup', function (e) {
                    e.preventDefault();
                    OpenPopup($(this).attr('href'));
                })
    
                function OpenPopup(pageUrl) {
                    var $pageContent = $('<div/>');
                    $pageContent.load(pageUrl, function () {
                        $('#popupForm', $pageContent).removeData('validator');
                        $('#popupForm', $pageContent).removeData('unobtrusiveValidation');
                        $.validator.unobtrusive.parse('form');
                    });
    
                    $dialog = $('<div class="popupWindow" style="overflow:auto"></div>')
                        .html($pageContent)
                        .dialog({
                            draggable: false,
                            autoOpen: false,
                            resizable: false,
                            model: true,
                            title: 'Popup Dialog',
                            height: 550,
                            width: 600,
                            close: function () {
                                $dialog.dialog('destroy').remove();
                            }
                        })
                    
                    $('.popupWindow').on('submit', '#popupForm', function (e) {
                        var url = $('#popupForm')[0].action;
                        $.ajax({
                            type: "POST",
                            url: url,
                            data: $('#popupForm').serialize(),
                            success: function (data) {
                                if (data.status) {
                                    $dialog.dialog('close')
                                    oTable.ajax.reload();
                                }
                            }
                        })
                        e.preventDefault();
                    })
                    $dialog.dialog('open');
                }
            });
        </script>
    </body>
    </html>
    
  • SnacklesSnackles Posts: 33Questions: 8Answers: 0

    Save.cshtml:

    @model Test2.Models.Employee
    
    <h2>Save</h2>
    @using (Html.BeginForm("save", "home", FormMethod.Post, new { id = "popupForm" }))
    {
        if (Model != null && Model.EmployeeID > 0)
        {
            @Html.HiddenFor(a => a.EmployeeID)
        }
    
        <div class="form-group">
            <label>First Name</label>
            @Html.TextBoxFor(a => a.FirstName, new { @class = "form-control" })
            @Html.ValidationMessageFor(a => a.FirstName)
        </div>
    
        <div class="form-group">
            <label>Last Name</label>
            @Html.TextBoxFor(a => a.LastName, new { @class = "form-control" })
            @Html.ValidationMessageFor(a => a.LastName)
        </div>
    
        <div class="form-group">
            <label>Email</label>
            @Html.TextBoxFor(a => a.EmailID, new { @class = "form-control" })
            @Html.ValidationMessageFor(a => a.EmailID)
        </div>
    
        <div class="form-group">
            <label>City</label>>
            @Html.TextBoxFor(a => a.City, new { @class = "form-control" })
            @Html.ValidationMessageFor(a => a.City)
        </div>
    
        <div class="form-group">
            <label>Country</label>>
            @Html.TextBoxFor(a => a.Country, new { @class = "form-control" })
            @Html.ValidationMessageFor(a => a.Country)
        </div>
    
        <div>
            <input type="submit" value="Save" />
        </div>
    }
    

    Delete.cshtml

    @model Test2.Models.Employee
    
    <h2>Delete Employee</h2>
    <h2>Save</h2>
    @using (Html.BeginForm("delete", "home", FormMethod.Post, new { id = "popupForm" }))
    {
        @Html.HiddenFor(a => a.EmployeeID)
        <div class="form-group">
            <label>First Name</label>
            <p>@Model.FirstName</p>
        </div>
    
        <div class="form-group">
            <label>Last Name</label>
            <p>@Model.LastName</p>
        </div>
    
        <div class="form-group">
            <label>Email</label>
            <p>@Model.EmailID</p>
        </div>
    
        <div class="form-group">
            <label>City</label>
            <p>@Model.City</p>
        </div>
    
        <div class="form-group">
            <label>Country</label>
            <p>@Model.Country</p>
        </div>
    
        <div>
            <input type="submit" value="Delete" />
        </div>
    }
    
  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin
    Answer ✓

    when I try to use the DataTables Editor buttons to do the same thing, no requests are made.

    You haven't defined an ajax option for the Editor initialisation. So it can't make any Ajax requests - instead it will just do local table editing. You need to use ajax to point it at your CRUD end point.

    Allan

  • SnacklesSnackles Posts: 33Questions: 8Answers: 0

    Hey Allan, thanks for the quick response!

    I can see the AJAX requests attempting now, but they're replying with errors. When I try to create a new entry I get a 500 Internal Server Error. I can see that when I use the working button it sends a GET and POST request; whereas, the Editor New button only sends a POST request and the Form data looks more like an array with the [data][0] and it's always [data][0] when I attempt.

    I'm assuming it's because I have /home/save/0 as the url in the create option of the ajax part, but even when I remove the 0 it still sends the request as [data][0]?

    Correct me if I'm wrong, but I need to find a way to incorporate the row's primary ID into the AJAX request? How would I do that?

    Something like this?:

    "data": function ( d ) {
                    d.myKey = "myValue";
                    // d.custom = $('#myInput').val();
                    // etc
                }
    

    This is the response I get using the Editor New button:

    This is the response I get using Add New buttonk:


    This is my new Editor initialization:

    editor = new $.fn.dataTable.Editor({
                    ajax: {
                        create: { type: 'POST', url: "/home/save/0"},
                        edit: { type: 'PUT', url: "/home/save/"},
                        remove: { type: 'DELETE', url: "/home/delete/"}
                    },
                    table: "#myDatatable",
                    idSrc: 'EmployeeID',
                    fields: [{
                        label: "First Name:",
                        name: "FirstName"
                    }, {
                        label: "Last Name:",
                        name: "LastName"
                    }, {
                        label: "Email:",
                        name: "EmailID"
                    }, {
                        label: "City:",
                        name: "City"
                    }, {
                        label: "Country:",
                        name: "Country"
                    }]
                });
    
  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin

    Correct me if I'm wrong, but I need to find a way to incorporate the row's primary ID into the AJAX request?

    For edit and delete use _id_ as shown in this example but for create you would normally just POST to /home/save (or whatever your route is) since it is the server that typically defines the primary key. It depends upon what your server expects exactly.

    Allan

  • SnacklesSnackles Posts: 33Questions: 8Answers: 0

    I found that example and tried it, but no luck. Maybe it's the way the controller is set up to handle the Http requests. It looks as if each CRUD operation starts with a Get request and then posts. Can I call both a Get and Post request in editor ajax option?

    Is the REST interface the best way to go about this or is there an easier method?

  • SnacklesSnackles Posts: 33Questions: 8Answers: 0

    I used the DataTables Editor Generator to create a working template that I think I'll build off of.

    Thanks a lot, Allan!

This discussion has been closed.