35
votes

I edit the grid using editable: "popup" as shown on Telerik's demo page. After I edit the grid, I want the grid to refresh. Does the grid have any event that is called after I edit the grid?

I tried to use the databound event. In this event I make the datasource read, but it tells me it is an infinite loop to refresh the grid. I tried to use the saveChanges event, but it is not working.

@(Html.Kendo().Grid<Kendo.Mvc.Examples.Models.ProductViewModel>()
.Name("grid")
.Columns(columns =>
{
    columns.Bound(p => p.ProductName);
    columns.Bound(p => p.UnitPrice).Width(100);
    columns.Bound(p => p.UnitsInStock).Width(100);
    columns.Bound(p => p.Discontinued).Width(100);
    columns.Command(command => { command.Edit(); command.Destroy(); }).Width(160);
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.PopUp))
.Pageable()
.Sortable()
.Scrollable()
  .Events(events => events.Change("saveChanges "))
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
    .Ajax()
    .PageSize(20)
    .Events(events => events.Error("error_handler"))
    .Model(model => model.Id(p => p.ProductID))
    .Create(update => update.Action("EditingPopup_Create", "Grid"))
    .Read(read => read.Action("EditingPopup_Read", "Grid"))
    .Update(update => update.Action("EditingPopup_Update", "Grid"))
    .Destroy(update => update.Action("EditingPopup_Destroy", "Grid"))
))
13

13 Answers

47
votes

You can subscribe to the Sync event of the grid's data source and call the read method of its data source.

.Events(events => events.Error("error_handler").Sync("sync_handler"))

function sync_handler(e) {
   this.read();
}
20
votes

Add Events into DataSource

.DataSource(dataSource => dataSource.Ajax(

        .Events(e => e.RequestEnd("PowerPlantProduction.onRequestEnd"))**
)

Javascript:

onRequestEnd: function (e) {

        if (e.type == "update") {
            if (!e.response.Errors) {
               e.sender.read();
            }
        }
    },
7
votes

The accepted answer can cause unexpected behaviour if you're using server side validation. The sync event triggers whenever an update is sent to the server regardless of whether the request was successful, so if the request triggers server side validation errors (or any other errors) the grid will still be updated and any changes lost. Still looking at the this but the best solution I've found is to use the data source's onRequestEnd() event and manually check for errors.

For example:

function onRequestEnd(e)
{
    var grid = $("#grid").data("kendoGrid");
    var data = grid.dataSource;
    if (e.type == "create" || e.type == "update") {
        if (!e.response.Errors) 
            data.read();
        else console.log("I had some issues");
    }
}
4
votes

This will refresh the Grid

 var grid = $("#Name").data("kendoGrid");
     grid.dataSource.page(1);

if .page(1) doesn't work try .read, but it should

4
votes

I agree this is very old question, but unfortunately I was also a victim of this error few days back. My scenario was

  1. First time i was able to insert new record in database using popup method
  2. If I add another record in same grid without refresh, grid is sending both the records to server, and unfortunately leads in duplicate value error.

Finally I think I got a solution for my problem, I was not setting primary key value to my record when I insert it into database and returning that object.

Below is my kendo grid code

@(Html.Kendo().Grid<TeamMemberViewModel>()
        .Name("Grid")
        .Columns(columns =>
        {
            columns.Bound(p => p.abcd);
            columns.Bound(p => p.abcd_id).Hidden();
            columns.Bound(p => p.abcd12_id).Hidden();
            columns.Command(command =>
            {
                command.Edit();
                command.Destroy();
            });
        })
        .ToolBar(toolbar =>
        {
            if (ViewBag.IsAddAllowed)
            {
                toolbar.Create().Text("Add new");
            }

            //  toolbar.Save().SaveText("Save Changes");

        })
        .Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("ABCD")
        )
        .Pageable()
        .Navigatable()
        .Sortable()
        .Scrollable()
        .DataSource(dataSource => dataSource
            .Ajax()                
            .PageSize(20)
            .ServerOperation(false)
            .Events(events =>
            {
                events.Error("error_handler");
                events.RequestEnd("request_end");
            }
)
        .Model(model =>
        {
            model.Id(p => p.primarykey_id);
            model.Field(p => p.abcd);
        })
        .Create("ABCD_Create", "TeamMember", new { id = Model.abcd_id})
        .Read("ABCD_Read", "TeamMember", new { id = Model.abcd_id })
        .Update("ABCD_Update", "TeamMember", new { id = Model.abcd_id })
        .Destroy("TeamMember_Destroy", "TeamMember", new { id = Model.hackathon_id })
    )
)

Below is error handling code

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



    function request_end(e) {
        switch (e.type) {
            case "create":
                if (e.Errors == undefined && e.response.Total > 0) {
                    //  alert("Saved Successfully");
                    $(".errorMessage").text("Saved Successfully");
                }
                break;

            case "update":
                if (e.Errors == undefined && e.response.Total > 0) {
                    // alert("Updated Successfully");
                    $(".errorMessage").text("Updated Successfully");
                }
                break;

            case "destroy":
                if (e.Errors == undefined && e.response.Total > 0) {
                    // alert("Deleted Successfully");
                    $(".errorMessage").text("Deleted Successfully");
                }
                break;

            default:
                $(".errorMessage").text("");
                break;
        }

        return true;
    }

Server Code

 [AcceptVerbs(HttpVerbs.Post)]
public ActionResult ABCD_Create([DataSourceRequest] DataSourceRequest request, MyViewModel my, short abcd_id)
{
    if (my != null && ModelState.IsValid)
    {

        MY tm = Mapper.Map<MyViewModel>(my);
        tm.abcd_id = abcd_id;

        try
        {
            repo.Create(tm);
            my.primarykey_id = tm.primarykey_id;   ///This is most important                           
        }
        catch (Exception ex)
        {
            ModelState.AddModelError("Duplicate Value Found", string.Format("error: {0} already exists", my.abcd));
        }
    }
    else
    {
        ModelState.AddModelError("Error", "Not valid please send data again");
    }

    return Json(new[] { my }.ToDataSourceResult(request, ModelState));
}

Hope this might help someone

3
votes

Use this if you want to refresh the grid.

$("#WorkOrderDetails").data("kendoGrid").refresh();
3
votes

using AutoSync(true) in ajax mvc kendo grid having pop up edit mode causes the pop up to not show up at all.

So I use this

function onRequestEnd(e) {
        if(e.type == "create" || e.type == "destroy" || e.type == "update") {
            setTimeout(function myfunction() {
                $("#mygrid").data("kendoGrid").dataSource.read();
            }, 1000);
        }
    }

The time out is to make sure you dont over lap the crud operation.

3
votes

In case someone else needs to know how to do this. You can include the "complete" function in your create as well as update bits.

transport: {
    read: {
        url: "http://myurl.json"
    },
    create: {
        url: "http://mycreate.json",
        type: "POST",
        complete: function(e) {
            $("#grid").data("kendoGrid").dataSource.read(); 
        }
    },
1
votes

You can call a function on you edit button click and inside that you can refresh the grid:

function EditRow(){
     var grid = $("#YourGridName").data("kendoGrid");
     grid.dataSource.read();              
}
1
votes
.sync: function (e) {
this.read();
},
0
votes

I've been trying to figure out how to refresh the grid after creating a new item. Scenario is: Create an item in the client, send request to server, receive response and update client. (Alternatively, I wouldn't mind figuring out why the grid isn't using the item I'm returning it in the server-side create function)

This post mentions the requestEnd event, but it's not exposed in razor. This event seems to fire after a request is finished, that is, after the server processes the event, so new objects created on the client will already be sent to the server for processing; then the client can request the latest information without losing data. Since the grid datasource object was undefined on page load, I ended up using the .Change event to hook the requestEnd event.

@(Html.Kendo().Grid
.Name("user-grid")
...
.Pageable(pageable => pageable
    ...
    .Events( e => e.Remove("grid_remove").Change("hook_request_end"))
.DataSource(dataSource => dataSource
    .Ajax()
    .PageSize(20)
    .Model(m =>
    {
        m.Id(vm => vm.DocumentId);
        m.Field<DateTime>("LastModified").Editable(false);
    })
    .Read(a => a.Action("KList", "Controller"))
    .Create(a => a.Action("KCreate", "Controller"))
    .Update(a => a.Action("KUpdate", "Controller"))
)

and then the javascript:

var requestEndHooked = false;
function hook_request_end()
{
    if (requestEndHooked == true)
    {
        return;
    }

    requestEndHooked = true;
    $("#user-grid").data("kendoGrid").dataSource.bind("requestEnd", dataSource_requestEnd);
}

function dataSource_requestEnd(e)
{
    try
    {
        if (e.type == "create")
        {
            $("#user-grid").data("kendoGrid").dataSource.read();
        }

    }
    catch (e)
    {
    }
}

If there's a better way, I'd love to know.

To answer your question, there are events other than "create": "read", "update"

0
votes

I know this is an old question, but there is a perfectly working example (at least for me!) on the Telerik forum: https://www.telerik.com/forums/refresh-grid-after-insert-update

I post this here because that forum question and answer is less than a year old, it might be that that solution wasn't available for the Kendo version at the time of the OP's question.

The solution mentioned there is to attach a dataBound handler function to the grid, which will be executed only once after the save event. In code:

function onGridEdit(e) {
    e.sender.one("dataBound", function (e) {
        e.sender.dataSource.read();
    });
}
 
function bindDataAndRefresh(e) {
    var grid = $("#upcoming-grid").data("kendoGrid");
    grid.bind("dataBound", onGridEdit(e));
}
 

$(document).ready(function () {
    var grid = $("#upcoming-grid").data("kendoGrid");
    grid.bind("save", bindDataAndRefresh);
});
0
votes

I used complete property of transport:update section while creating datasource for kendo.

My code

 dsource = new kendo.data.DataSource({
            transport: {
                read: {
                    url: serverapiUrl + "/emp",
                    type: 'GET',
                    dataType: "json",
                    cache: true,
                    beforeSend: function (xhr, settings) {
                        xhr.setRequestHeader('api-key', 'auth key');
                    }
                },
                create: {
                    url: serverapiUrl + "/emp",
                    type: 'POST',
                    dataType: 'json',
                    beforeSend: function (xhr, settings) {
                        console.log('under create');
                        xhr.setRequestHeader('api-key', 'authkey');
                        xhr.setRequestHeader("content-type", "application/json"); 
                        console.log('settings', settings);
                        console.log(xhr);
                    }
                },
                update: {
                    url: serverapiUrl + "/emp",
                    type: 'PUT',
                    dataType: 'json',                        
                    beforeSend: function (xhr, settings) {
                        console.log('under update');
                        xhr.setRequestHeader('api-key', 'authkey');
                        xhr.setRequestHeader("content-type", "application/json");                                                        
                        console.log('settings', settings);
                        console.log(xhr);
                    },
                    complete: function (eve) {
                        console.log('update complete');
                        $("#griddiv").data("kendoGrid").dataSource.read();
                    }
                }

rest follows the normal structure of kendo ui datasource creation documentation.