This is a migrated thread and some comments may be shown as answers.

Prevent kendo ui grid popup editor from closing after validation errors

5 Answers 1932 Views
Grid
This is a migrated thread and some comments may be shown as answers.
west
Top achievements
Rank 1
west asked on 19 Jan 2017, 12:50 PM

I am returning errors from server and catch it in kendo datasource error event.In this event I am trying to prevent close popup editor, but it works only first time, after clicking update second time, the window closes.
I searched a lot but could not find a solution

 

City = {
    InitializeGrid: function () {
 
        function LoadCities(url, success) {
            Common.serverRequest(url, success);
        }
 
        function UpdateCity(url, params, success) {
            Common.serverRequestParams(url, params, success);
        }
 
        function InsertCity(url, params, success) {
            Common.serverRequestParams(url, params, success);
        }
 
        function DeleteCity(url, id, success) {
            Common.serverRequestParams(url, id, success);
        }
 
        dataSource = new kendo.data.DataSource({
            transport: {
                read: function (e) {
                    LoadCities("/home/read", function (res) {
                        e.success(res);
                    });
                },
 
                update: function (e) {
 
                    UpdateCity("/home/update", e.data, function (res) {
                        var grid = $("#grid").data("kendoGrid");
                        if (res.success) {
                            grid.dataSource.read();
                        } else {
                            e.error("", "", res.error);
                            grid.cancelChanges();
                        }
 
                    });
                },
                create: function (e) {
                    InsertCity("/home/insert", e.data, function (res) {
                        var grid = $("#grid").data("kendoGrid");
 
                        if (res.success) {
                            grid.dataSource.data(res.data);
                        } else {
                            e.error("", "", res.error);
                            grid.cancelChanges();
                        }
                    });
                },
                destroy: function (e) {
                    DeleteCity("/home/delete", e.data, function (res) {
                        var grid = $("#grid").data("kendoGrid");
 
                        if (res.success) {
                            grid.dataSource.data(res.data);
                        } else {
                            e.error("", "", res.error);
                            grid.cancelChanges();
                        }
 
                    });
                }
            },
            error: function (e) {
                var grid = $("#grid").data("kendoGrid");
                grid.one("dataBinding", function (e) {
                    e.preventDefault(); // it occures only first time
                });
                alert(e.errorThrown);
 
            },
            pageSize: 20,
            schema: {
                model: {
                    id: "Id",
                    fields: {
                        Name: { type: "string" },
                        EndDate: { type: "date" },
                        CreateDate: { type: "date" }
                    }
                }
            }
        });
 
        $("#grid").kendoGrid({
            dataSource: dataSource,
            height: 750,
            selectable: "single",
            filterable: true,
            sortable: true,
            pageable: true,
            toolbar: [{ name: "newRecord", text: "New Record" }, { name: "editRecord", text: "Edit REcord" }, { name: "deleteRecord", text: "Delete" }],
            columns: [
                { field: "Name", title: "Name" },
                { field: "EndDate", title: "End Date", format: "{0:dd.MM.yyyy hh:mm}" },
                { field: "CreateDate", title: "Create Date", format: "{0:dd.MM.yyyy hh:mm}" }
            ],
            editable: {
                mode: "popup",
                confirmation: false,
                template: kendo.template($("#popup_editor").html())
            }
        });
 
        $("#grid").on("click", ".k-grid-newRecord", function () {
            Common.gridAdd('grid', 'New Record');
        });
 
        $("#grid").on("click", ".k-grid-editRecord", function () {
            Common.gridEdit('grid', 'Edit Record');
        });
 
        $("#grid").on("click", ".k-grid-deleteRecord", function () {
            Common.gridDelete('grid');
        });
 
    }
}

 

mvc controler

public class HomeController : Controller
    {
        List<City> cities;
        public string error { get; set; }
        public bool isSuccess { get; set; } = true;
         
 
        public ActionResult Index()
        {
            cities = new List<City>();
            Session["city"] = cities;
            return View();
        }
 
        public ActionResult Read()
        {
            var result = (List<City>)Session["city"];
            return Json(result);
        }
 
        public ActionResult Update(City item)
        {
            var result = (List<City>)Session["city"];
 
            if (string.IsNullOrEmpty(item.Name))
            {
                error = "Name is required";
                isSuccess = false;
            }
 
            result.Where(w => w.Id == item.Id).SingleOrDefault(s => s == item);
 
            return Json(new { success = isSuccess, error =error, data = item });
        }
 
        public ActionResult Insert(City item)
        {
            var result = (List<City>)Session["city"];
 
            item.Id = result.Count;
            item.Id++;
 
            if (string.IsNullOrEmpty(item.Name))
            {
                error = "Name is required";
                isSuccess = false;
            }
 
            result.Add(item);
 
            return Json(new { success = isSuccess, error = error, data = item });
        }
 
        public ActionResult Delete(City item)
        {
            var result = (List<City>)Session["city"];
 
            result.Remove(item);
 
            return Json(new { success = isSuccess });
        }
    }

5 Answers, 1 is accepted

Sort by
0
Alex Hajigeorgieva
Telerik team
answered on 23 Jan 2017, 09:14 AM
Hello West,

If I understand you correctly, you need to prevent the Kendo UI Grid popup editable window from closing when the entered data is invalid. This behaviour is built-in when the schema model field validation object is configured:

http://docs.telerik.com/kendo-ui/api/javascript/data/model#methods-Model.define 

A demo which shows both the built-in validation as well as a custom rule is shown in the official demos site here:

http://demos.telerik.com/kendo-ui/grid/editing-custom-validation

Finally, I would like to propose removing the Kendo UI Grid logic from the data source entirely. Since the data source is bound to the grid, the grid will get updated automatically. Just call e.success/e.error for the create, update and delete operations( the read operation is grid-free so it can stay that way). I believe the code should be something similar to the below:

update: function (e) {
 UpdateCity("/home/update", e.data, function (res) {
  if (res.success) {
    e.success()
   } else {
    e.error("", "", res.error);
   }
 });
},
create: function (e) {
 InsertCity("/home/insert", e.data, function (res) {
  if (res.success) {
     e.success(e.data);
  } else {
     e.error("", "", res.error);
  }
 });
},
destroy: function (e) {
 DeleteCity("/home/delete", e.data, function (res) {
  if (res.success) {
     e.success();
  } else {
     e.error("", "", res.error);
  }
 });
}

Let me know if I misunderstood the question, so I can promptly provide a more appropriate response.

Kind Regards,
Alex Hajigeorgieva
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data (charts) and form elements.
0
riz
Top achievements
Rank 1
answered on 21 May 2019, 09:44 PM
I'm not the original poster, but am in a similar situation. It seems that you have misunderstood the original question as the poster states in their first line: "I am returning errors from server and catch it in kendo datasource error event."  Whereas you are talking about doing input model validation on the client side, the user is talking about errors being returned from the server. Once the client input validation is successful, we still have to validate on the backend, and the popup should still remain open if the validation fails on the server end to allow the user to fix the errors otherwise it's frustrating to re-enter the data. Do you have a solution for this?
0
Alex Hajigeorgieva
Telerik team
answered on 23 May 2019, 11:56 AM

Hi, Riz,

Thank you for noting that the original poster has described a data source error which is coming from a remote service. I believe you are correct and that I have misunderstood the post.

I created a sample Dojo  using a mocked error response here that shows how to keep the popup open and notify the errors:

https://dojo.telerik.com/@bubblemaster/OGUlAKIL

Here are the important parts: 

- specify which part of the response contains the errors

https://docs.telerik.com/kendo-ui/api/javascript/data/datasource/configuration/schema#schemaerrors 

- add an error handler in the data source. It will be triggered when the field which contains the errors is present in the response
- prevent the grid to bind. This will keep the popup open and notify the user that there are errors:

// data source error handler 
error: function(e) {
  grid.one("dataBinding", function (ev) {
    ev.preventDefault();
    var message = "Errors:\n";           
    $.each(e.errors, function (idx, error) {            
       message += "Code: "
         + error.code
         + " | Reason: " + error.reason
         + "\n";
    });
    kendo.alert(message);
  });
}

I hope this helps.

Kind Regards,

Alex Hajigeorgieva
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
riz
Top achievements
Rank 1
answered on 28 Jun 2019, 11:23 PM
Thanks Alex, but I am getting an error "Uncaught TypeError: Cannot read property 'one' of undefined".  I think in this case 'dataBinding' parameter is the name of the grid?  My error handler in this case is generic and my application has many grids possibly with different names, so I can't explicitly specify the name of the grid as you have. Is there a way to fetch the name of the grid from the 'e' parameter of the error handler?
0
Alex Hajigeorgieva
Telerik team
answered on 02 Jul 2019, 08:26 AM
Hello, Riz,

The Kendo UI DataSource has no knowledge of the grid or other data bound widgets to which it could be simultaneously bound to. So the error event which the data source emits and its event data cannot give us the grid's instance. This is done on purpose to comply with quality code and the Separation of Concerns design principle.

In your scenario, do you have the same data source bound to different grids on the same page? Could you please provide an example of the exact case in which you are not able to get the grid instance?

I am unsure if this would help but each grid has a data-role="grid" attribute and if only one grid is in edit mode, perhaps we could use that to get to the correct instance.

Look forward to hearing back from you so I can better understand the details.

Regards,
Alex Hajigeorgieva
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
Grid
Asked by
west
Top achievements
Rank 1
Answers by
Alex Hajigeorgieva
Telerik team
riz
Top achievements
Rank 1
Share this question
or