In this demo we show how we can achieve instant (on keyup, change) validation for grid inline editors.
By default we only have ajax validation, when the save ajax request is processed on the server we may get back validation errors.
Besides the validation rules defined in the ViewModel (server side), in this demo we also added a few validation rules present only on the client:
* Name can't contain "asdf"
* When Organic is true Name.length can't be less than 5.
GridInlineClientValidation/Index.cshtml
@{ var grid2Id = "DinnersGrid2"; var initObj = new { Name = DemoUtils.RndName(), Date = DateTime.Now.ToShortDateString(), ChefId = Db.Chefs.First().Id, MealsIds = Db.Meals.Take(2).Select(o => o.Id).ToArray() }; } <div class="bar"> <button type="button" onclick="$('#@grid2Id').data('api').inlineCreate()" class="awe-btn">Create</button> @Html.InlineCreateButtonForGrid(grid2Id, initObj, "Create with predefined values") <button type="button" onclick="$('#@grid2Id').data('api').batchSave()" class="awe-btn">Save All</button> <button type="button" onclick="$('#@grid2Id').data('api').inlineCancelAll()" class="awe-btn">Cancel All</button> </div>
@*grid client validation (for MVC5 call to BindOvld must be placed in a cshtml with @model DinnerInput)*@
@(Html.BindOVldForId<DinnerInput>(grid2Id, b => { b.Prop("Name", "noAsdf", "Name can't contain asdf");
b.Prop("Name", "organicNameMinLen", "Name length can't be less than 5 when Organic = yes"); b.Relate("Organic", "Name"); // when checking Organic Name will also be updated }))
<script> function noAsdf(o) { return o.v.indexOf('asdf') !== -1; }
function organicNameMinLen(o) { var row = o.inp.closest('.awe-row'); var org = row.find('[name="Organic"]'); var name = row.find('[name="Name"]');
// below properties used for inline editing only MealsIds = o.Meals.Select(m => m.Id.ToString()).ToArray(), // value for meals multiselect ChefId = o.Chef.Id, // value for chef dropdown BonusMealId = o.BonusMeal.Id // value for bonus meal dropdown }; }
public IActionResult GridGetData(GridParams g, string search = "") { var query = Db.Dinners.Where(o => o.Name.Contains(search)).AsQueryable();
var model = new GridModelBuilder<Dinner>(query, g) { KeyProp = o => o.Id, // needed for api select, update, tree, nesting, EF Map = MapToGridModel, };
return Json(model.Build()); }
[HttpPost] public IActionResult BatchSave(DinnerInput[] inputs) { var res = new List<object>();
foreach (var input in inputs) { var vldState = ModelUtil.Validate(input);
// custom validation example if (input.Name != null && input.Name.Contains("aaa")) { vldState.Add("Name", "Name can't contain aaa"); }
if (vldState.IsValid()) { try { var isCreate = !input.Id.HasValue;
var ent = isCreate ? new Dinner() : Db.Dinners.First(o => o.Id == input.Id);