Okay, so I have a grid that is used to manage Users. I would like to have two edit-popup buttons,
1.) For changing the user's password
2.) For changing the rest of the user's information
I currently have 1 command.Edit() button that has a custom template specified in ".Editable" that works fine with changing the user's information.
I would like to have a second button that is associated with a different template that changes the user's password.
I thought that this could be achieved through a Command.Custom() button; however, I'm not sure how I'd hook it up to the Grid's edit event.
Is this even possible? If not, is there any known workaround to achieve this functionality?
Kind regards,
Ruben
5 Answers, 1 is accepted
So, I just thought of a possible solution. If I have two "command.Edit()" buttons, one for changing the password and one for changing the rest of the user information. Like so,
columns.Command(command => command.Edit().UpdateText("Save User")).Title("Edit User").Width(60);columns.Command(command => command.Edit().UpdateText("Save Password")).Title("Edit Password").Width(60);
I then define a template defined in Editable like so,
.Editable(editable => editable .TemplateName("ManageUsersEditor") .Mode(GridEditMode.PopUp) .Window(window => { window.HtmlAttributes(new { @class = "kendo-popup-editor" }); window.Title("User account"); }) )
I subscribe to the Edit Event like so,
.Events(events => events.Edit("onEdit"))
Could I add logic in the "onEdit" function to determine which Edit button was pressed? If so how would that logic look?
<script> function onEdit(e) { // determine which edit button was pressed // can I do a check on the "Update Text" or any other field? if (!e.model.isNew()) { e.container.find(".passwordEditor").remove(); } }</script>
Any help is greatly appreciated! Thanks.
Ruben
I am afraid that the described behavior is not available out of the box. However, you can implement it with a bit of additional code.
You can define a custom popup editor and wrap the editors in div elements that will be conditionally hidden when necessary. The popup editor can be roughly structured like below:
<div class="customVisible"> some custom editors that will be conditionally hidden</div><div>other editors.</div>Then, you can specify custom command buttons:
columns.Command(cmd => cmd.Custom("Edit1").Click("edit1Handler"));columns.Command(cmd => cmd.Custom("Edit2").Click("edit2Handler"));The Click handlers for each custom command will set a global variable that will determine what part of the editor will be visible to the user:
var someFlag;function edit1Handler(e) { var grid = this; var row = $(e.target).closest("tr")[0]; someFlag = "edit1"; grid.editRow(row);}function edit2Handler(e) { var grid = this; var row = $(e.target).closest("tr")[0]; someFlag = "edit2"; grid.editRow(row);}Finally you can handle the Grid edit event and hide/show the relevant parts of the editor:
.Events(e=>e.Edit("onEdit"))function onEdit(e) { if (someFlag == "edit1") { e.container.find(".customVisible").hide(); }}Give the appraoch a try and let me know how it works for you.
Regards,
Viktor Tachev
Progress Telerik
Hi Viktor,
Thank you for the help! I implemented your suggestion, and it works except for the password fields are autofilled with some erroneous data that I'm assuming might be the user information that I hid. Any idea how I could resolve this? Here is my current implementation:
// ManageUsers.cshtml@model ERMgtProgram.Models.ManageViewModels.ManageUsersViewModel@{ ViewBag.Title = "Manage Users";}<h2>@ViewBag.Title.</h2><h4>Modify data management accounts</h4><p class="text-success">@ViewBag.StatusMessage</p><div> @(Html.Kendo().Grid<ERMgtProgram.Models.ManageViewModels.ManageUsersViewModel>() .Name("manageUsersGrid") .Columns(columns => { columns.Bound(c => c.FirstName).Width(100); columns.Bound(c => c.LastName).Width(100); columns.Bound(c => c.Email).Width(100); columns.Bound(c => c.RolesList).ClientTemplate("#= roleListDetails(data) #").Width(100).Sortable(false).Filterable(false).Groupable(false); columns.Command(command => command.Custom("Edit1").Click("edit1Handler")).Title("Edit User").Width(60); columns.Command(command => command.Custom("Edit2").Click("edit2Handler")).Title("Edit Password").Width(60); columns.Command(command => command.Destroy()).Title("Delete User").Width(60); }) .Editable(editable => editable .TemplateName("ManageUsersEditor") .Mode(GridEditMode.PopUp) .Window(window => { window.HtmlAttributes(new { @class = "kendo-popup-editor" }); window.Title("User account"); }) ) .ToolBar(toolbar => { toolbar.Create().Text("Add new user"); }) .HtmlAttributes(new { style = "height: 700px;" }) .Scrollable(s => s.Height(700)) .Groupable() .Sortable() .Pageable(pageable => pageable .Refresh(true) .PageSizes(new int[] { 10, 20, 50, 100, 250, 1000 }) .ButtonCount(5)) .Filterable() .Events(events => events.Edit("onEdit")) .DataSource(dataSource => dataSource .Ajax() .Model(m => { m.Id(c => c.Id); m.Field(c => c.Id).Editable(false); m.Field(c => c.RolesList); }) .Events(events => events.RequestEnd("onRequestEnd").Error("errorHandler")) .Create(create => create.Action("Users_Create", "Manage").Data("sendAntiForgery")) .Read(read => read.Action("Users_Read", "Manage")) .Update(update => update.Action("Users_Edit", "Manage").Data("sendAntiForgery")) .Destroy(destroy => destroy.Action("Users_Delete", "Manage").Data("sendAntiForgery")) ) )</div><script> var someFlag; function edit1Handler(e) { var grid = this; var row = $(e.target).closest("tr")[0]; someFlag = "edit1"; grid.editRow(row); } function edit2Handler(e) { var grid = this; var row = $(e.target).closest("tr")[0]; someFlag = "edit2"; grid.editRow(row); }</script><script> function onEdit(e) { // if model is not new then user pressed an edit button if (!e.model.isNew()) { if (someFlag == "edit1") { e.container.find(".passwordEditor").hide(); } else if (someFlag == "edit2") { e.container.find(".userEditor").hide(); } } }</script><script> // displays server-side validation messages errorHandler = function (args) { if (args.errors) { var grid = $("#manageUsersGrid").data("kendoGrid"); var validationTemplate = kendo.template($("#userDetailsValidationMessageTemplate").html()); grid.one("dataBinding", function (e) { e.preventDefault(); $.each(args.errors, function (propertyName) { var renderedTemplate = validationTemplate({ field: propertyName, messages: this.errors }); grid.editable.element.find(".errors").append(renderedTemplate); }); }); } };</script><script type="text/x-kendo-template" id="userDetailsValidationMessageTemplate"> # if (messages.length) { # <li> #=field# <ul> # for (var i = 0; i < messages.length; ++i) { # <li>#= messages[i] #</li> # } # </ul> </li> # } #</script><script> // refreshes grid after create or update operations function onRequestEnd(e) { var grid = $("#manageUsersGrid").data("kendoGrid"); var data = grid.dataSource; if (e.type == "create" || e.type == "update") { if (!e.response.Errors) data.read(); } }</script><script> // displays the roles for a particular user in a grid cell function roleListDetails(model) { var htm = ""; for (var roleNumber in model.RolesList) { htm = htm + "<p> " + model.RolesList[roleNumber].Name + "</p>"; if (roleNumber >= model.RolesList.length - 1) { break; } } var html = kendo.format(htm); return html; }</script><script> // posts antiforgery token function sendAntiForgery() { return { "__RequestVerificationToken": $('input[name=__RequestVerificationToken]').val() } }</script>
// MangeUsersEditor.cshtml@using Kendo.Mvc.UI;@model ERMgtProgram.Models.ManageViewModels.ManageUsersViewModel<ul class="errors"></ul><div class="userEditor"> <div class="editor-label"> @Html.LabelFor(m => m.FirstName) </div> <div class="editor-field"> @Html.EditorFor(m => m.FirstName) @Html.ValidationMessageFor(m => m.FirstName) </div> <div class="editor-label"> @Html.LabelFor(m => m.LastName) </div> <div class="editor-field"> @Html.EditorFor(m => m.LastName) @Html.ValidationMessageFor(m => m.LastName) </div> <div class="editor-label"> @Html.LabelFor(m => m.Email) </div> <div class="editor-field"> @Html.EditorFor(m => m.Email) @Html.ValidationMessageFor(m => m.Email) </div> <div class="editor-label"> @Html.LabelFor(m => m.RolesList) </div> <div class="editor-field"> @(Html.Kendo().MultiSelectFor(m => m.RolesList) .DataTextField("Name") .DataValueField("Id") .IgnoreCase(true) .AutoBind(true) .DataSource(datasource => { datasource.Read(read => read.Action("ReadRolesList", "Manage")); }) ) @Html.ValidationMessageFor(m => m.RolesList) </div></div><div class="passwordEditor"> <div class="editor-label"> @Html.LabelFor(m => m.Password) </div> <div class="editor-field"> @Html.EditorFor(m => m.Password) @Html.ValidationMessageFor(m => m.Password) </div> <div class="editor-label"> @Html.LabelFor(m => m.ConfirmPassword) </div> <div class="editor-field"> @Html.EditorFor(m => m.ConfirmPassword) @Html.ValidationMessageFor(m => m.ConfirmPassword) </div></div>
I've also attached some screenshots to give a visual representation of how it looks. Note: everything validates fine, but the password fields are autopopulated with erroneous data and instead I would like for them to be empty.
Solution: I ended up just setting the password fields manually to override it, like so:
function edit2Handler(e) { var grid = this; var row = $(e.target).closest("tr")[0]; someFlag = "edit2"; grid.editRow(row); document.getElementById("Password").value = ""; document.getElementById("ConfirmPassword").value = "";}
Thanks for all the help!
