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

Multiple Editable Events for 1 Grid

5 Answers 613 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Ruben
Top achievements
Rank 1
Ruben asked on 28 Sep 2017, 01:36 PM

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

Sort by
0
Ruben
Top achievements
Rank 1
answered on 28 Sep 2017, 03:29 PM

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

 

0
Viktor Tachev
Telerik team
answered on 02 Oct 2017, 12:50 PM
Hello 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
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 visualization (charts) and form elements.
0
Ruben
Top achievements
Rank 1
answered on 02 Oct 2017, 03:36 PM

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. 

 

0
Ruben
Top achievements
Rank 1
answered on 02 Oct 2017, 04:00 PM
Update: I am fairly confident that the password field is being auto-filled with the password hash stored in my User DB. 
0
Ruben
Top achievements
Rank 1
answered on 03 Oct 2017, 04:05 PM

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!

Tags
Grid
Asked by
Ruben
Top achievements
Rank 1
Answers by
Ruben
Top achievements
Rank 1
Viktor Tachev
Telerik team
Share this question
or