How to return messages to client from grid actions

1 Answer 186 Views
Grid
Luke
Top achievements
Rank 2
Iron
Iron
Iron
Luke asked on 06 May 2022, 04:58 PM

Hello,

I would like to return messages to the client whenever a grid create or edit action has completed successfully. I have tried adding to the Json being returned and using VeiwData/TempData but neither is a viable option with the ToDataSourceResult of the grid action methods. I can't seem to find any documentation on how I can achieve this. Please point me in the right direction. Below is an action method I converted from being a grid action to using my own modal editing but I'd like to use the built in grid popup instead.

        [HttpPost]
        public IActionResult Update([DataSourceRequest] DataSourceRequest request, CaseRequestVM vm, bool fromDashboard = false)
        {
            if (ModelState.IsValid)
            {
                bool caseRequestUpdated = _caseRequestService.UpdateCaseRequest(vm);
                if (caseRequestUpdated)
                {
                    TempData["Message"] = "Case request updated."; // ===> SHOW ON CLIENT
                }
                else
                {
                    TempData["Message"] = "Failed to update case request";
                }
            }
            else
            {
                TempData["Message"] = "Failed to update case request";
            }

            if (!fromDashboard)
                return RedirectToAction(nameof(Index));
            else
                return RedirectToAction("Dashboard", "Home");
        }

1 Answer, 1 is accepted

Sort by
1
Stoyan
Telerik team
answered on 11 May 2022, 01:01 PM

Hello Luke,

To show a message when the Create, Update and Destroy actions are successful, I'd recommend you to combine the DataBound Event of the Grid with the RequestEnd and Error Events of the DataSource  on the client-side to get information for the action that was executed.

DataSource

.Events(ev => ev.Error("onError").RequestEnd("onEnd"))

Grid

.Events(ev => ev.DataBound("onDataBound"))

The RequestEnd Event is thrown first and in it you can get the type of the request and set its type to a global variable. 

var successfullOperation = "";    
function onEnd(e) {
        if (e.type == "destroy") {
            successfullOperation = "deleted"
        } else if (e.type == "update") {
            successfullOperation = "updated"
        } else if (e.type == "create") {
            successfullOperation = "created"
        }
  } 

Next the Error Event is thrown, if the server action failed. In the handler set the global variable to an empty string to ensure the success message won't popup when an error occurs.

function onError(e) {
        successfullOperation = "";
        if (e.errors) {
            var message = "Errors:\n";
            $.each(e.errors, function (key, value) {
                if ('errors' in value) {
                    $.each(value.errors, function () {
                        message += this + "\n";
                    });
                }
            });
            alert("error");
        }
    }

Then in the DataBound Event handler, if the global variable success message is not an empty string show the success message. 

    function onDataBound(e) {
        if (successfullOperation.length > 0) {
            alert("Row was successfully "+successfullOperation)
        }
        successfullOperation = "";
    }

Finally, make sure to reset the global variable to prevent the success message to popup unintentionally.

For your convenience I have attached a sample project that showcases the steps above.

Regards,
Stoyan
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Luke
Top achievements
Rank 2
Iron
Iron
Iron
commented on 11 May 2022, 03:41 PM

Thank you for the response Stoyan! I believe this will work great for what I need. It will take me some time to implement, but it is added to my task list. I will mark this as an answer once I've had the opportunity to try it out. I appreciate the assistance.
Luke
Top achievements
Rank 2
Iron
Iron
Iron
commented on 13 May 2022, 05:38 PM

Hey Stoyan,

I am implementing your solution and it is working out fantastic so far. I would like to implement your onError handler across multiple grids and my previous error handlers are grid specific. How can I access the grid in the handler without using the grid id? The following shows your implementation added to one of my grids. I'd like to use this same handler for many grids though.

function ErrorHandler(args) {
    successfullOperation = "";
    var errors = args.errors;
    if (errors) {
        var grid = $("#Agencies").data("kendoGrid"); // HOW CAN I GET THIS USING THE PARAMETER ARGS?
        grid.one("dataBinding", function (e) {
            e.preventDefault(); // Prevent data binding when errors occured.
            $.each(errors, function (key, value) {
                var message = "";
                if ('errors' in value) {
                    $.each(value.errors, function () {
                        message += this + "\n";
                    });
                }

                // As long as the key matches the field name, this line of code will be displayed as validation message in the popup.
                grid.editable.element.find("[data-valmsg-for='" + key + "']").replaceWith('<div class="k-widget k-tooltip k-tooltip-error" style="margin:0.5em"><span class="k-icon k-i-warning"> </span>' + message + '<div class="k-callout k-callout-n"></div></div>').show();
            });
        });
    }
}

Stoyan
Telerik team
commented on 18 May 2022, 12:56 PM | edited

Hi Luke,

I am happy the suggested approach has been helpful so far.

In regard to generalizing the error handler for different Grids you can use closures to pass the Grid's name as parameter to the error handler since the content of the DataSource's Error Event cannot access directly the Grid that called it:

.Events(ev => ev.Error("ErrorHandler(myGridName)"))
function errorHandler(gridName) {
  return function(e) {
     var grid = $(gridName).data("kendoGrid");
     // handle the event  
  };
}

For more information on the topic I'd recommend the related forum thread How to get grid name inside error event?

Tags
Grid
Asked by
Luke
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
Stoyan
Telerik team
Share this question
or