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

Confirmation on row selection change

3 Answers 607 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Andrei
Top achievements
Rank 1
Andrei asked on 22 May 2014, 08:36 PM
Hello,

I have Master/Detail page layout where on the left side of the page there is Kendo Grid with the list of items and on the right side of the page there is specific item details.

I want to prompt confirmation message to the user if changes were done in the detail section and user clicked on the different item in the list of items grid prior to saving changes.

Initially, I though I should be able to catch "click" event and based on the prompt popup result either do nothing or apply 

e.stopPropagation();
e.preventDefault();
e.stopImmediatePropagation();

   function selectionValidation() {
       // Place your validation logic here
       return confirm("Change selection");
   }
 
onGridDataBound: function () {
           // Intercept click event to prevent row from loosing focus
           // if user decide not to loose changes done in the detail section
           this.grid.tbody.find("tr[class='templated-row ']").click(this.checkDataChanged);
     },
 
       checkDataChanged: function (e) {
           newValues = $('form').serialize();
 
           if (initialValues !== newValues) {
                   if (selectionValidation()) {
                   } else {
                       e.stopPropagation();
                       e.preventDefault();
                       e.stopImmediatePropagation();
               }
           }
       },


Apparently it is not working with click event in the Kendo Grid as selection within the grid changes prior to firing "click" event. I guess I just do not know where to hook my click event.

So then I decided to hook up to the mousedown event, which help me prevent row selection prior to closing prompt popup, but it looks like event chain breaks and no normal "click"-related processing happens. Row stays unselected and no change event fires.

Did I miss something? Can you suggest best way to achieve required functionality (prompt user prior to selecting row different from the one currently selected)?


Thank you,

Andrei

3 Answers, 1 is accepted

Sort by
0
Accepted
Dimiter Madjarov
Telerik team
answered on 23 May 2014, 01:25 PM
Hi Andrei,


Indeed the behavior is exactly the same as described. The event is not propagated due to the many internal checks in the Kendo UI user events, which ensure the same user experience on all kinds of devices. I won't go in detail about this, but as for the current case, you could use the same approach with the confirm box and manually select the row if the condition is satisfied.
E.g.
$("#Grid tbody").on("mousedown", "tr", function (e) {
    var ok = confirm("Change selection?");
 
    if (ok) {
        $("#Grid").data("kendoGrid").select(this);
    }
});

I hope this information helps.

Regards,
Dimiter Madjarov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Andrei
Top achievements
Rank 1
answered on 26 May 2014, 03:57 PM
Thank you Dimiter,

Your solution worked in Chrome, but not IE.

Seems like something withing the grid triggering change event and it happens before user able to close prompt box.

I tried following, but no matter what - when I click on the item within the grid with list of items - my detail pane gets refreshed with the info from the clicked on item.

Did I miss something and there is another event I need to unbind in order to prevent click event propagation?

onGridDataBound: function () {
    this.grid.tbody.click(this.onTest);
    this.grid.tbody.find("tr").click(this.onTest);
    this.grid.tbody.find("td").click(this.onTest);
    this.grid.tbody.find("div").click(this.onTest);
 
    this.grid.tbody.mousedown(this.onTest);
    this.grid.tbody.find("tr").mousedown(this.onTest);
    this.grid.tbody.find("td").mousedown(this.onTest);
    this.grid.tbody.find("div").mousedown(this.onTest);
 
    this.grid.tbody.mouseup(this.onTest);
    this.grid.tbody.find("tr").mouseup(this.onTest);
    this.grid.tbody.find("td").mouseup(this.onTest);
    this.grid.tbody.find("div").mouseup(this.onTest);
 
    this.executeCallbacks(this.gridDataBoundCallbacks);
 
    if (this.grid.tbody.find("tr[class='templated-row ']") != null) {
 
        // Intercept mousedown event to prevent row from loosing focus
        // if user decide not to loose changes done in the detail section
        // NOTE: As per Telerik's response - we cannot use click event:
        this.grid.tbody.find("tr[class='templated-row ']").mousedown(this.checkDataChanged);
        // Due to the custom logic - ajax call to get updated information into the data grid after saving details
        // we need to implement custom selection logic to re-select selected item in the grid.
        this.reSelectRow();
    }
 
},
 
onTest: function (e) {
    e.stopPropagation();
    e.preventDefault();
},
 
reSelectRow: function (e) {
    if (lastSelection == null) {
        // Saves first selection
        lastSelection = $("#grid .k-state-selected");
    } else {
        newSelection = $("#grid .k-state-selected");
 
        if (newSelection.length == 0) {
            $("#" + this.options.GridName).data('kendoGrid').tbody.find("tr[data-uid='" + $("#" + this.options.GridName).data('kendoGrid').dataSource.get(this.dataId).uid + "']").addClass("k-state-selected");
        }
    }
 
},
 
checkDataChanged: function (e) {
    // User about to change selection of the grid or leave the page.
    // Lets serialize the page and compare it to the value captured
    // in the "Is Dirty logic" section within site.js
    newValues = $('form').serialize();
 
    // If newly selected row - check if details data has been changed
    if (initialValues !== newValues) {
        var myGrid = $(document).find("div[data-role='grid']").data("kendoGrid");
 
        e.preventDefault();
        e.stopPropagation();
 
        var ok = confirm("Are you sure you want to continue?\nCancel will return you to the unsaved detail section.\nOK will discard your changes and change selected list item.");
 
        // If data has been changed - prompt confirmation
        if (ok) {
            // If yes - proceed with row change
            // AS: This is the only way I found to reference the grid. Maybe it can be done better...
            myGrid.select(this);
        }
    }
 
},



0
Andrei
Top achievements
Rank 1
answered on 26 May 2014, 08:39 PM
I got it.

The trick for the IE was to remove class "k-selectable" from the table before popping confirmation pop-up. Chrome, as I mentioned before, was working without this trick, but still working with the change :-).

onGridDataBound: function () {
    if (this.grid.tbody.find("tr[class='templated-row ']") != null) {
        // Intercept mousedown event to prevent row from loosing focus
        // if user decide not to loose changes done in the detail section
        // NOTE: As per Telerik's response - we cannot use click event:
        this.grid.tbody.find("tr[class='templated-row ']").mousedown(this.checkDataChanged);
 
        // Due to the custom logic - ajax call to get updated information into the data grid after saving details
        // we need to implement custom selection logic to re-select selected item in the grid.
        this.reSelectRow();
    }
 
},
 
checkDataChanged: function (e) {
    // User about to change selection of the grid or leave the page.
    // Lets serialize the page and compare it to the value captured
    // in the "Is Dirty logic" section within site.js
    newValues = $('form').serialize();
 
    // If newly selected row - check if details data has been changed
    if (initialValues !== newValues) {
        var myGrid = $(document).find("div[data-role='grid']").data("kendoGrid");
 
        // For IE - remove "k-selectable" class, so selection would not change
        // until user makes his/her choice on prompt pop-up.
        if (myGrid.table.hasClass("k-selectable")) {
            myGrid.table.removeClass("k-selectable");
        }
 
        var ok = confirm("Are you sure you want to continue?\nCancel will return you to the unsaved detail section.\nOK will discard your changes and change selected list item.");
 
        // If data has been changed - prompt confirmation
        if (ok) {
            // If yes - proceed with row change
            if (!myGrid.table.hasClass("k-selectable")) {
                myGrid.table.addClass("k-selectable");
            }
 
            // AS: This is the only way I found to reference the grid. Maybe it can be done better...
            myGrid.select(this);
        }
    }
 
},
 
reSelectRow: function (e) {
    if (lastSelection == null) {
        // Saves first selection
        lastSelection = $("#grid .k-state-selected");
    } else {
        newSelection = $("#grid .k-state-selected");
 
        if (newSelection.length == 0) {
            $("#" + this.options.GridName).data('kendoGrid').tbody.find("tr[data-uid='" + $("#" + this.options.GridName).data('kendoGrid').dataSource.get(this.dataId).uid + "']").addClass("k-state-selected");
        }
    }
 
},



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