I use the Ajax Editing to manage the record in my grid .
I would like call the controller before edit the selected record to check if the record is not lock.
I would like have this process :
- Click on "Edit" buttom on grid,
- Call the action controller to check the lock,
-> If record lock, Abort Edit record,
-> If record is not lock, Edit record.
Do you know of a great way to make this process ?
Thanks
I set up a simple grid like this using the Razor syntax:
@(Html.Kendo().Grid<
GridCustomPopupTemplate.Models.Person
>().Name("persons")
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(m => m.PersonID))
.Read(read => read.Action("GetPersons", "Home"))
.Update(up => up.Action("UpdatePerson", "Home"))
)
.Columns(columns =>
{
columns.Bound(c => c.PersonID).Width(200);
columns.Bound(c => c.Name);
columns.Command(cmd => {
cmd.Edit();
});
})
.Pageable()
.Sortable()
.Editable(ed => ed.Mode(GridEditMode.PopUp).TemplateName("Person"))
)
8 Answers, 1 is accepted
Hello Leoni,
My suggestion is to use a custom command button as shown in the Grid / Custom command demo, make the request to the server to check whether the selected record is locked and based on the response open the popup editor for the data item. This could be done by calling the editRow method of the Kendo UI DataSoure and pass the jQuery row element.
Regards,
Boyan Dimitrov
Telerik

Thank you Boyan for your answer.
I have used the basic custom command buttons and "edit" event to call action controller with ajax request.The ajax request check the record status : lock or unlock :
- If record is locked then the record is null and the popup edit is close. This process work fine.
- If record is unlocked then record return the last version record (record different of Master grid, if an user has modified the record after display of the grid).
My issue being that the trigger event of the "update" buttom doesn't work after update the setting the model (set.model). The "CTCO_PRENOM" field content the last value, but the popup edit is always display after click "update".
I have noticed that the "requestEnd" event type of datasource return "undefined" (See enclosed file).
Why the trigger event of the "update" buttom is disabled after the ajax return ?
I'm beginning to use telerik UI for asp .net mvc and i don't know if a good way for edit record of master grid. I found examples with the partial Views.
What is your suggestion ?
I continue this way or change method. Do you have a code library aspnet-mvc to explain this process ?
Regards.
View Master Grid:
<div
class
=
"col-xs-18 col-md-12"
>
@* Grille
"Contact"
*@
@(Html.Kendo().Grid<CSE.Model.ContactEntity>().Name(
"grid"
)
.Columns(columns =>
{
// Command disponible au niveau de la grille
columns.Command(command =>
{
command.Edit();
command.Destroy();
}).Width(200);
columns.Bound(p => p.CTCO_ID);
columns.Bound(p => p.CTCO_CIVILITE);
columns.Bound(p => p.CTCO_PRENOM);
columns.Bound(p => p.CTCO_EMAIL);
columns.Bound(p => p.CTCO_FONCTION).Filterable(ftb => ftb.Multi(
true
));
columns.Bound(p => p.CTCO_LIB);
})
.ToolBar(toolbar => toolbar.Create())
// Mode d'édition
.Editable(editable =>
{
editable.Mode(GridEditMode.PopUp).TemplateName(
"ContactResultEntityTable"
);
})
.Pageable()
.Events(e =>
{
// Edit event to call action controller
e.Edit(
"onRequestEdit"
);
e.Cancel(
"onRequestClose"
);
})
.Sortable()
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Model(model =>
{
model.Id(p => p.ID);
})
.Events(events =>
{
events.Error(
"onError"
);
events.RequestEnd(
"onRequestEnd"
);
})
.Create(update => update.Action(
"Create"
,
"Contacts"
))
.Update(update => update.Action(
"Update"
,
"Contacts"
))
.Destroy(update => update.Action(
"Destroy"
,
"Contacts"
))
.Read(r Optionsead => read.Action(
"Search"
,
"Contacts"
).Data(
"additionalInfo"
)
)
)
)
</div>
Javascript in View :
// Event : Edit Record (coté client): Appel Controller "CheckLock"
function
onRequestEdit(arg) {
// get model
var
model = arg.model;
//model.sender.read();
alert(
"onRequestEdit"
);
kendoConsole.log(
"onRequestEdit : Edit : "
+ model.CTCO_ID +
":"
+ model.CTCO_PRENOM);
grid = $(
"#grid"
).data(
"kendoGrid"
);
// Appel de la méthode "CheckLock" en passant ID du contact pour vérifier le lock sur l'enregistrement.
$.ajax({
url:
'@Url.Action("CheckLock", "Contacts")'
,
type:
'POST'
,
data: { ID: model.CTCO_ID },
//data: JSON.stringify(model),//{ contactAtLock: model.},
datatype :
'json'
,
success:
function
(result) {
//if (result.rlock) {
if
(result.contact !=
null
&& result.contact !== undefined) {
// Edit de l'enregistrement possible
alert(
'onRequestEdit : Edit record :'
+ result.contact.CTCO_ID +
"Prenom->"
+ result.contact.CTCO_PRENOM);
// Mise à jour de l'enregistrement
for
(
var
property
in
result.contact) {
model.set(property, result.contact[property]);
}
}
if
(result.contact ==
null
) {
// Edition de l'enregistrement impossible
alert(
'Edit: Record verrouillé par un autre utilisateur'
);
$(
'span.k-i-close'
).click();
}
},
error:
function
() { alert(
'Error in popup edit'
); }
})
}
// Event : Abort Edit (coté client): Appel Controller "UnLock"
function
onRequestClose(arg) {
var
model = arg.model;
// Call de la méthode "UnLock" en passant ID du contact pour vérifier le lock sur l'enregistrement.
$.ajax({
url:
'@Url.Action("UnLock", "Contacts")'
,
data: { ID: model.CTCO_ID },
success:
function
(result) {
if
(result.rlock) {
// Enregistrement courant déverouillé
alert(
'onRequestClose : Record unlock'
);
}
}
})
}
// Event : Edit End : Forcer la lecture de la source en cas d'update (Spécifique au Template Custom)
function
onRequestEnd(e) {
kendoConsole.log(
"onRequestEnd : Start : event type :"
+ e.type);
if
(e.type ==
"update"
) {
alert(
"onRequestEnd : Update"
);
//Get Grid
var
grid = $(
"#grid"
).data(
"kendoGrid"
);
grid.dataSource.read();
}
}
function
onError(e, status) {
if
(e.errors) {
var
message =
"There are some errors:\n"
;
// Create a message containing all errors.
$.each(e.errors,
function
(key, value) {
if
(
'errors'
in
value) {
$.each(value.errors,
function
() {
message +=
this
+
"\n"
;
});
}
});
// Display the message
alert(message);
// Cancel the changes
var
grid = $(
"#grid"
).data(
"kendoGrid"
);
grid.cancelChanges();
}
}
My Template PopupEdit (Form) :
@model CSE.Model.ContactEntity
<html>
<head>
<
base
href=
"http://demos.telerik.com/kendo-ui/integration/bootstrap"
>
<title>My Custom PopUpEdit</title>
</head>
<body>
<div id=
"inputWindow"
class
=
"responsive-table-line"
style=
"margin:0px auto;max-width:700px;"
>
<table
class
=
"table table-bordered table-condensed table-body-center"
>
<tbody>
<br />
@Html.HiddenFor(model => model.ID)
<tr>
<td>
<div
class
=
"form-group"
>
@Html.LabelFor(model => model.CTCO_CIVILITE)
</div>
</td>
<td>
<div
class
=
"form-group"
>
@Html.EditorFor(model => model.CTCO_CIVILITE)
@Html.ValidationMessageFor(model => model.CTCO_CIVILITE)
</div>
</td>
</tr>
<tr>
<td>
<div
class
=
"form-group"
>
@Html.LabelFor(model => model.CTCO_LIB)
</div>
</td>
<td>
<div
class
=
"form-group"
>
<div
class
=
"form-group"
>
@Html.EditorFor(model => model.CTCO_LIB)
@Html.ValidationMessageFor(model => model.CTCO_LIB)
</div>
</div>
</td>
</tr>
<tr>
<td>
<div
class
=
"form-group"
>
@Html.LabelFor(model => model.CTCO_PRENOM)
</div>
</td>
<td>
<div
class
=
"form-group"
>
@Html.EditorFor(model => model.CTCO_PRENOM)
@Html.ValidationMessageFor(model => model.CTCO_PRENOM)
</div>
</td>
</tr>
<tr>
<td>
<div
class
=
"form-group"
>
@Html.LabelFor(model => model.CTCO_EMAIL)
</div>
</td>
<td>
<div
class
=
"form-group"
>
@Html.EditorFor(model => model.CTCO_EMAIL)
@Html.ValidationMessageFor(model => model.CTCO_EMAIL)
</div>
</td>
</tr>
<tr>
<td>
<div
class
=
"form-group"
>
@Html.LabelFor(model => model.CTCO_FONCTION)
</div>
</td>
<td>
<div
class
=
"form-group"
>
@Html.EditorFor(model => model.CTCO_FONCTION)
@Html.ValidationMessageFor(model => model.CTCO_FONCTION)
</div>
</td>
</tr>
<tr>
<td>
<div
class
=
"form-group"
>
@Html.LabelFor(model => model.CTCO_PUBLIC)
</div>
</td>
<td>
<div
class
=
"form-group"
>
@Html.EditorFor(model => model.CTCO_PUBLIC)
@Html.ValidationMessageFor(model => model.CTCO_PUBLIC)
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Controller :
[AcceptVerbs(HttpVerbs.Post)]
public
ActionResult CheckLock([DataSourceRequest] DataSourceRequest request,
int
ID)
//public ActionResult CheckLock(ContactEntity contactAtLock)
{
ContactEntity cto =
null
;
ContactEntity lastVersionContact =
null
;
if
(ModelState.IsValid)
{
// Vérifier que l'enregistrement courant n'est pas verrouillé par un autre utilisateur
//IManager manager = new ContactManager();
InitManager();
(manager
as
ContactManager).AuthenticationManager = (IAuthenticationManager)Session[
"UserManager"
];
//A l'ouverture de la fiche : Verifier si le contact peut être éditer
//todo: cto a stocker
cto = manager.EditElement(ID)
as
ContactEntity;
//Vérifier si on peut modifier
if
(manager.CanEdit(ID))
{
// Simuler Modification du record si valeur différente de la grille
cto.CTCO_PRENOM =
"lastVersion_"
+ cto.CTCO_PRENOM;
lastVersionContact = cto;
}
}
return
Json(
new
{ contact = lastVersionContact }, JsonRequestBehavior.AllowGet);
//.ToDataSourceResult(request, ModelState));
//return Json(new[] { lastVersionContact }.ToDataSourceResult(request, ModelState));
}
// Déverrouiller l'enregistrement
[AcceptVerbs(HttpVerbs.Post)]
public
ActionResult UnLock(
int
ID)
{
var result =
false
;
if
(ModelState.IsValid)
{
InitManager();
(manager
as
ContactManager).AuthenticationManager = (IAuthenticationManager)Session[
"UserManager"
];
//var entity = manager.EditElement(ID);
//todo: supprimer
var entity = manager.GetElement(ID);
// Si utilisateur annule les modifications
manager.Release(entity);
result =
true
;
}
return
Json(
new
{ rlock = result }, JsonRequestBehavior.AllowGet);
}
// MÃ J un "Contact"
[AcceptVerbs(HttpVerbs.Post)]
public
ActionResult Update([DataSourceRequest] DataSourceRequest request, ContactEntity contact)
{
bool
hasErrors = ModelState.Values.Any(x => x.Errors.Count > 1);
// Test
if
(contact !=
null
&& ModelState.IsValid)
{
int
id = contact.ID;
// Récupérer le manager courant
InitManager();
(manager
as
ContactManager).AuthenticationManager = (IAuthenticationManager)Session[
"UserManager"
];
// Travailler Directement avec l'entitié récupérer
var entity = (ContactEntity)contact;
// A la fermeture de la fiche
// Si utilisateur clic sur save
manager.Save(entity);
// Si utilisateur annule les modifications
//manager.Release(entity);
}
return
Json(
new
[] { contact }.ToDataSourceResult(request, ModelState));
}
Hello Leoni,
Actually the "Update" button in the popup editor will perform an update request to the server. Basically what you are trying to achieve is to perform a validation before the actual update.
In this case there is another possible solution: to prevent the default behavior when the "Update" button is clicked in order to perform the validation. If it is successful to call the sync method of the Kendo UI DataSource and if not - to show a message or something else.
Preventing the default behavior when "Update" button is clicked can be done in the save event handler of the Kendo UI Grid. Please refer to the code snippet below:
save:
function
(e){
e.preventDefault();
//here goes the validation logic and so on
},
In order to get the Kendo UI DataSource for the gird widget you can use the dataSource property of the Kendo UI Grid widget.
Regards,
Boyan Dimitrov
Telerik

Hello Boyan,
Yes, I would like to update the popup Edit with the last version record from the database after the lock.
I followed your suggestions, but the update method is not called after sync DataSource. I modified :
Add : save event handler of kendi UI Grid :
@(Html.Kendo().Grid<CSE.Model.ContactEntity>().Name("grid")
.Columns(columns =>
....
.Events(e =>
{
// Edit event to call action controller
e.Edit("onRequestEdit");
e.Cancel("onRequestClose");
e.Save("onRequestSave"); // SM 10/11/2015
})
Add save function :
function onRequestSave(arg) {
kendoConsole.log("Grid data onRequestSave");
arg.preventDefault;
kendoConsole.log("Grid data onRequestSave : preventDefault");
var grid = $("#grid").data("kendoGrid");
grid.dataSource.sync(); // The Update method is not called ?
}
I have forgotten somebody ?
Thanks.
Regards.

In addition to the reply below :
For "CheckLock" method in Controller :
[AcceptVerbs(HttpVerbs.Post)]
public
ActionResult CheckLock([DataSourceRequest] DataSourceRequest request,
int
ID)
//public ActionResult CheckLock(ContactEntity contactAtLock)
{
ContactEntity cto =
null
;
ContactEntity lastVersionContact =
null
;
if
(ModelState.IsValid)
{
//IManager manager = new ContactManager();
InitManager();
(manager
as
ContactManager).AuthenticationManager = (IAuthenticationManager)Session[
"UserManager"
];
// SM 03/09/2015
cto = manager.EditElement(ID)
as
ContactEntity;
//Check modified
if
(manager.CanEdit(ID))
{
// Simulate update record in database (data different of grid)
cto.CTCO_PRENOM =
"lastVersion_"
+ cto.CTCO_PRENOM;
lastVersionContact = cto;
}
}
// Return last version record to update all fields in popupEdit
return
Json(
new
{ contact = lastVersionContact }, JsonRequestBehavior.AllowGet);
}
Event : onRequestEdit() event grid :
function onRequestEdit(arg) {
....
$.ajax({
url:
'@Url.Action("CheckLock", "Contacts")'
,
type:
'POST'
,
data: { ID: model.CTCO_ID },
//data: JSON.stringify(model),//{ contactAtLock: model.},
datatype:
'json'
,
success: function (result) {
if
(result.contact !=
null
&& result.contact !== undefined) {
for
(var property
in
result.contact) {
// SM 13/11/2015 : Update record in popup Edit
arg.model.
set
(property, result.contact[property]);
//}
}
}
if
(result.contact ==
null
) {
// Close automatically PopPup
alert(
'Edit: Record verrouillé par un autre utilisateur'
);
$(
'span.k-i-close'
).click();
}
Hello Leoni,
The preventDefault is actually a method, so it should be called as a method:
arg.preventDefault();
Please find attached a sample project that implements the desired behavior.
Regards,
Boyan Dimitrov
Telerik

Hello Boyan,
Thank you for your sample project.
I have seen this error in my code.
I compared and checked my code but i don't understand why the update bottom action is not called after "sync" DataSource in onRequestSave event. The edit popup display until.
I was wondering what the real problem is.
The issue may be with the update record process after the ajax resquest (see below) because this process disables the status of master grid (change row). In addition, the "RequestEnd" event of master grid return "undefined". why ?
See enclosed, the controller and view code files.
I ask myself if this is possible.
What is your opinion?
Thanks,
Regards.
Hello Leoni,
Calling the sync method of the Kendo UI DataSource in the save event handler of the Kendo UI Grid is not supported scenario. At this time the model is not updated with the new value ( the event is preventable). My suggestion is to have a button that will call the sync method of the Kendo UI DataSource.
Regards,
Boyan Dimitrov
Telerik