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

Grid inline editing with server side validation errors

6 Answers 1703 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Thottempudi
Top achievements
Rank 1
Thottempudi asked on 11 May 2014, 04:34 PM
hi guys,
Server side validations it will support or not ?
I currently have a working grid with inline editing. I need validation that needs to be done on the server side because duplicate records checking..

Please check the code and let me know any issues in this code? or send me working sample code....

View code...

        @(Html.Kendo().Grid<PeopleTray.Models.Admin.EmploymentTypeModel>()
                .Name("gridEmployementType")
                .Columns(columns =>
                {
                    columns.Command(command => { command.Edit().Text("Edit").HtmlAttributes(new { title = "Edit" }); command.Destroy().Text("Delete").HtmlAttributes(new { title = "Delete" }); }).Width(160);
                    columns.Bound(p => p.Name);
                    columns.Bound(p => p.Description);
                    columns.Bound(w => w.Id).Hidden();                    
                    
                })
                .ToolBar(toolbar => toolbar.Create().Text("Add").HtmlAttributes(new { title="Add" }))
                .Editable(editable => editable.Mode(GridEditMode.InLine).CreateAt(GridInsertRowPosition.Bottom))               
                .Pageable(pager => pager.Refresh(true))
                .Sortable(sortable => sortable.AllowUnsort(true))
                .Events(e => e.Edit("onEdit")) 
                .Events(e => e.Save("onSave"))                              
                .HtmlAttributes(new { style = "width: 70%;" })
                .DataSource(dataSource => dataSource
                    .Ajax()
                    .ServerOperation(false)
                    .Events(events => events.Error("error_handler"))
                    .PageSize(5)
                    .Model(model =>
                    {
                        model.Id(ds => ds.Id);
                    })
                    .Create(create => create.Action("EmployementType_Insert", "CorporateAdmin"))
                    .Read(read => read.Action("EmployementTypes_Read", "CorporateAdmin"))
                    .Update(update => update.Action("EmployementType_Update", "CorporateAdmin"))
                    .Destroy(destroy => destroy.Action("EmployementType_Delete", "CorporateAdmin"))
                )
            )
 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";
                    });
                }
            });
            alert(message);
        }
    }
--------------------------
Controller code.....

public ActionResult EmployementType_Insert([DataSourceRequest]DataSourceRequest request, EmploymentTypeModel model)
        {
            var employementtypes = AdminService.GetEmployementTypesModel();
            for (int r = 0; r < employementtypes.Count; r++)
            {
                if (employementtypes[r].Name.ToLower() == model.Name.Trim().ToLower())
                {
                    ModelState.AddModelError("grid_error", "The employement type already exists. Please modify or delete your entry.");
                    return Json(new[] { model }.ToDataSourceResult(request, ModelState));
                }
            }
            if (model.Name != null && ModelState.IsValid)
            {
                AdminService.InsertEmploymentType(model);               
            }
            return Json(new[] { model }.ToDataSourceResult(request, null), JsonRequestBehavior.AllowGet);
        }


6 Answers, 1 is accepted

Sort by
1
Dimiter Madjarov
Telerik team
answered on 13 May 2014, 12:43 PM
Hi Thottempudi,


The provided sample code seems correct. The recommended approach in the current case would be to use the error event handler of the dataSource in order to prevent the next dataBinding of the Grid in the case of some server errors.
E.g.
function error(args) {       
    if (args.errors) {
        var grid = $("#Grid").data("kendoGrid");
        grid.one("dataBinding", function (e) {  
            e.preventDefault();   // cancel grid rebind if error occurs                                             
        });
    }
}

The complete approach is demonstrated in the following Code Library. It targets the PopUp edit mode, but the same approach could be used with InLine too.

Regards,
Dimiter Madjarov
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Donald
Top achievements
Rank 1
answered on 16 Jul 2015, 02:59 PM

Hi Dimiter,

 I have been using that code block for a while, but it is no longer working after an update to 2015 Q2. Is there a known issue? I can't seem to find anything on ​it. The popup editor is displaying the error, but closing anyway once kendo.all.js is hit.

 

0
Donald
Top achievements
Rank 1
answered on 16 Jul 2015, 03:02 PM
Nevermind, seems to be working. I had a call to dataSource.read() on sync that will need to change
0
DHHS
Top achievements
Rank 1
answered on 28 Jul 2015, 10:28 PM

I have hierarchical grid with inline editing. server validations on parent grid is working fine, but server validations on child grid, i am not sure how to achieve. If the model has some errors , how would view understands which grid it is and take to proper error event?

If the child grid error event is hit, how to get the grid id of child grid so that i can search for field names? 

Parent grid
 
@(Html.Kendo().Grid<BHEBS.Areas.Admin.Models.BHFormsModel.BHForms>()
    .Name("BHForms")
    .Columns(columns =>
    {
        columns.Bound(e => e.Id).Width(140).Filterable(false).Width(50).Hidden(true);
        columns.Bound(e => e.BHFormsName).Width(300);
        columns.Bound(e => e.BHFormsDesc);
        columns.Command(command =>
            {
                command.Edit().HtmlAttributes(new { @class = "btn-primary" });
                command.Destroy().HtmlAttributes(new { @class = "btn-primary" });
            }).Width(350);
    })
    .Events(e => e.Edit("onEdit"))
    .ToolBar(tools => tools.Create().Text("Add BH Forms").HtmlAttributes(new { @class = "btn-primary" }))
    .Pageable().Sortable().Filterable()
    .DataSource(source => source.Ajax()
            .Model(model =>
                {
                    model.Id(e => e.Id);
                    model.Field(e => e.Id).Editable(false);
                })
                   .Events(events => events.Error("error"))
                .Read(read => read.Action("Read_BHForm", "BHForms"))
                .Update(update => update.Action("Update_BHForm", "BHForms"))
                .Create(create => create.Action("Create_BHForm", "BHForms"))
                .Destroy(destroy => destroy.Action("Destroy_BHForm", "BHForms")))
    .ClientDetailTemplateId("ExpenseCatBHFormTemplate")
)
 
Child Grid
 
<script type="text/kendo" id="ExpenseCatBHFormTemplate">
    @(Html.Kendo().Grid<BHEBS.Areas.Admin.Models.BHFormsModel.ExpenseCategoryBHForm>()
        .Name("ExpenseCatBHForm_#=Id#")
        .Columns(columns =>
        {
            columns.Bound(o => o.EC_Id).Hidden(true);
            columns.Bound(o => o.BHF_Id).Hidden(true);
            columns.Bound(o => o.ExpenseCategory);
            columns.Bound(o => o.ExpenseType).Width(140).Filterable(false).Width(50).Hidden(true);
            columns.Bound(o => o.ExpenseTypeName).Width(200);
            columns.Bound(o => o.StartDate).Format("{0:MM/dd/yyyy}").Width(220);
            columns.Bound(o => o.EndDate).Format("{0:d}").Width(220);
            columns.Command(command =>
            {
                command.Edit().HtmlAttributes(new { @class = "btn-primary" });
                command.Custom("Delete").SendDataKeys(true).Click("deleteClick").HtmlAttributes(new { @class = "btn-primary" });
            }).Width(350);
        }).ToolBar(toolbar =>
                {
                    toolbar.Template(@<text>
                        <div class="toolbar">
                            <button class="k-button k-button-icontext k-primary" id="expenseCatAddBtn">Add Expense Category</button>
                        </div>
                    </text>);
                })
            //.ToolBar(tools => tools.Create())
                        .Pageable().Sortable().Filterable()
                        .DataSource(source => source.Ajax()
                                    .Model(model =>
                                            {
                                                model.Id(o => o.EC_Id);
                                                model.Field(o => o.EC_Id).Editable(false);
                                                model.Field(o => o.ExpenseCategory).Editable(false);
                                                model.Field(o => o.ExpenseTypeName).Editable(false);
                                            })
                                    .Events(events => events.Error("errorchild"))
                            .Read(read => read.Action("Read_ExpenseCat", "BHForms", new { id = "#=Id#" }))
                            .Update(update => update.Action("Update_ExpenseCat", "BHForms", new { id = "#=Id#" }))
            //.Create(create => create.Action("Create_ExpenseCat", "BHForms", new { id = "#=Id#" }))
            //.Destroy(destroy => destroy.Action("Destroy_ExpenseCat", "BHForms", new { id = "#=Id#" }))
                            )
                        .ToClientTemplate()
    )
 
</script>
 
<script type="text/kendo-template" id="message">
    <div class="k-widget k-tooltip k-tooltip-validation k-invalid-msg field-validation-error" style="margin: 0.5em; display: block; " data-for="#=field#" data-valmsg-for="#=field#" id="#=field#_validationMessage">
        <span class="k-icon k-warning"> </span>#=message#<div class="k-callout k-callout-n"></div>
    </div>
</script>
 
 
    var validationMessageTmpl = kendo.template($("#message").html());  
 
    function error(args) {
        if (args.errors) {
            var grid = $("#BHForms").data("kendoGrid");
            grid.one("dataBinding", function (e) {
                e.preventDefault();   // cancel grid rebind if error occurs                            
 
                for (var error in args.errors) {                 
                        showMessage(grid.editable.element, error, args.errors[error].errors);                   
                }
            });
        }
    }
 function errorchild(args) {
        if (args.errors) {
            var grid = $("#BHForms").data("kendoGrid"); //how to get child grid
            grid.one("dataBinding", function (e) {
                e.preventDefault();   // cancel grid rebind if error occurs                            
 
                for (var error in args.errors) {                 
                        showMessage(grid.editable.element, error, args.errors[error].errors);                   
                }
            });
        }
    }
    function showMessage(container, name, errors) {
        //add the validation message to the form
        container.find("[data-valmsg-for=" + name + "],[data-val-msg-for=" + name + "]")
        .replaceWith(validationMessageTmpl({ field: name, message: errors[0] }))
    }

0
Dimiter Madjarov
Telerik team
answered on 30 Jul 2015, 08:54 AM

Hello DHHS,

In order to overcome the issue, you could use a proxy function and pass the Grid name as additional parameter to the error handler.
E.g.

@(Html.Kendo().Grid<OrderViewModel>()
    .Name("Orders_#=EmployeeID#")
    .DataSource(source => source.Ajax()
        .Events(e => e.Error(@<text>
            function(args) {
                var gridName = 'Orders_#=EmployeeID#';
                 errorSubGrid(args, gridName);
            }
        </text>))

function errorSubGrid(args, gridName) {
    if (args.errors) {
        var subGrid = $("#" + gridName).data("kendoGrid");

I wish you a great day!

Regards,
Dimiter Madjarov
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
DHHS
Top achievements
Rank 1
answered on 30 Jul 2015, 02:18 PM

Perfect Dimiter. You are awesome.

 

Thanks,

Veena

Tags
Grid
Asked by
Thottempudi
Top achievements
Rank 1
Answers by
Dimiter Madjarov
Telerik team
Donald
Top achievements
Rank 1
DHHS
Top achievements
Rank 1
Share this question
or