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

Help with "catching" an event AFTER the grid is fully loaded / rendered

5 Answers 3947 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Vlad
Top achievements
Rank 1
Vlad asked on 18 Feb 2016, 11:42 AM

Hello.

I'm having a problem implementing the following scenario:

After the grid is loaded (binding to local data), in some cases, I need to apply the filters, paging, and selection from a previous state of the grid. If I do this inside the databound event, this will cause an infinte loop (as I've read and experience first-hand). How / where can I add the code from ApplyPreviousSettings (see below js code) so that it can work automatically?

E.g. of scenario in cause.

When on page "Users\Index" filter the grid (filterMode = row), change page (if necessary), and select an item.

Click on Edit (which redirects the edit page for the selected user) - at the point of leaving the "Users\Index" , I save in localstorage the grid's state (not all of it - only filter, paging and selection)

When clicking on Save or Cancel, the Index page (with the grid) will be displayed AND it is at this time that I want to "restore" the grid according to the data in the localstorage.

 

I've attached screenshots for the above scenario and a video.

The grid looks like this:

@(Html.Kendo().Grid(Model)
          .Name("Grid")
          .Columns(columns =>
          {
              columns.Bound(p => p.Id).Title("#= Id #").Hidden(true).HtmlAttributes(new { id = "#= Id #" });
              columns.Bound(p => p.FirstName).Title(Resource.Firstname).Filterable(f => f.Cell(c => c.Operator("Contains").ShowOperators(false).Template("EnableAutoFiltering")));
              columns.Bound(p => p.Name).Title(Resource.Lastname).Filterable(f => f.Cell(c => c.Operator("Contains").ShowOperators(false).Template("EnableAutoFiltering")));
              columns.Bound(p => p.EmailAddress).Title(Resource.Email).Filterable(f => f.Cell(c => c.Operator("Contains").ShowOperators(false).Template("EnableAutoFiltering")));
              columns.Bound(p => p.CompletelyEquiped).Title(Resource.CompletelyEquipped)
                  .ClientTemplate("<div style='text-align: center;'><input type='checkbox' value='#= CompletelyEquiped #' disabled='disabled' " +
                                  "# if (CompletelyEquiped) { #" +
                                  "checked='checked'" +
                                  "# } #" +
                                  "/> </div>").Filterable(filterable =>
                                      filterable.Messages(m => m.IsFalse(Resource.No_UserIndex))
                                          .Messages(m => m.IsTrue(Resource.Yes_UserIndex)));

              columns.Bound(p => p.BusinessUnit).Title(Resource.BusinessUnit_UserCreate).Filterable(f => f.Cell(c => c.Operator("Contains").ShowOperators(false).Template("EnableAutoFiltering")));
              columns.Command(c => c.Destroy());
          })
          .ToolBar(toolbar =>
          {

              toolbar.Template(@<text>
                                   <div class="toolbar">
                                       <a href="@Url.Action("Create", "User")" class="k-button k-button-icontext" id="CreateButton"><span class='k-icon k-add'></span>@Resource.Create</a>
                                       @Html.Kendo().Button().Name("EditButton").Content(Resource.Edit).Events(e => e.Click("EditClick")).SpriteCssClass("k-icon k-edit")

                                   </div>
                                </text>);
          })
          .HtmlAttributes(new {style = "width: 125%;"})
          .Pageable(pageable => pageable.Input(true).Numeric(false))
          .Sortable()
          .Events(e => e.DataBound("CustomizeFilterMenu"))
          .Selectable(s => s.Mode(GridSelectionMode.Single))
          .Filterable(ftb => ftb.Mode(GridFilterMode.Row))
          .DataSource(dataSource => dataSource
               .Ajax()
              .ServerOperation(false)
              .Model(model => model.Id(p => p.Id))
              .PageSize(10)
              .Destroy("Delete", "User")

          ))

Javascript:

 

function EnableAutoFiltering(args) {
    args.element.css("width", "90%").addClass("k-textbox").keydown(function (e) {
        setTimeout(function () {
            $(e.target).trigger("change");
        });
    });
}

function EditClick() {
    var grid = $('#Grid').data("kendoGrid");

    var selectedItem = grid.dataItem(grid.select());

    if (selectedItem == null) {
        alert("Please select row!");
    } else {
        if (window.location.pathname.endsWith("Index")) {
            window.location = "../User/Edit/" + selectedItem["Id"];
        } else {
            window.location = "../" + window.location.pathname.split("/")[1] + "/User/Edit/" + selectedItem["Id"];
        }

    }
}

function ApplyPreviousSettings() {
        var gridOptions = localStorage["kendo-grid-options"];
        if (gridOptions === "null" || gridOptions === undefined) {

        } else {
            var grid = $("#Grid").data("kendoGrid");

            var state = JSON.parse(gridOptions);

            grid.dataSource.filter(state.filter);
            grid.pager.page(parseInt(state.page));
            var row = $("#Grid").find("tbody>tr>td[id= " + state.selectedUserId + "]").parent();
            grid.select(row);


        }
}

function CustomizeFilterMenu(args) {
    var parents = $(":radio").parent();
    if (!$(parents[0]).hasClass("RadioButtonFilterStyle")) {
        $(parents[0]).addClass("RadioButtonFilterStyle");
    }
}
window.onbeforeunload = function (e) {
    if (e.target.activeElement.id === "EditButton" || e.target.activeElement.id === "CreateButton") {
        var grid = $("#Grid").data("kendoGrid");
        var dataSource = grid.dataSource;
        var state =
            {
                page: dataSource.page(),
                filter: dataSource.filter(),
                selectedItem : grid.dataItem(grid.select()),
                selectedUserId : grid.dataItem(grid.select()).Id
            };
        localStorage["kendo-grid-options"] = kendo.stringify(state);
    } else {
        localStorage["kendo-grid-options"] = null;
    }
};

$(document).ready(function () {
    $("#KendoGrid").removeAttr("hidden");
    kendo.ui.progress($("KendoGrid"), false);
   
});

 

Important things to note: 

Under the grid (as seen in the screenshots) there is a button which does (if I click it manually) exactly what I need to do automatically (the button with text: "ceva") - the button calls the js method ApplyPreviousSettings. 

 

Also, here is a link to a video I've recorded, that I hope will clarify even further what I want to do.

 

https://www.dropbox.com/s/14wb1vuz76sr3st/sampleVideo2.zip?dl=0

Thank you.

Vlad

5 Answers, 1 is accepted

Sort by
0
Vlad
Top achievements
Rank 1
answered on 18 Feb 2016, 01:01 PM

UPDATE

 

I've managed to achieve the desired behaviour via a javascript timer. Code is posted below

function setGridState() {
    if (RebindGridState === true) {
        ApplyPreviousSettings();
        RebindGridState = false;
        abortTimer(GridStateTimer);
    }
}

function ApplyPreviousSettings() {
    var gridOptions = localStorage["kendo-grid-options"];
    if (gridOptions === "null" || gridOptions === undefined) {

    } else {
        var grid = $("#Grid").data("kendoGrid");

        var state = JSON.parse(gridOptions);

        grid.dataSource.filter(state.filter);
        grid.pager.page(parseInt(state.page));
        var row = $("#Grid").find("tbody>tr>td[id= " + state.selectedUserId + "]").parent();
        grid.select(row);
    }
}

function abortTimer(timer) {
    clearInterval(timer);
}

// This method is the one being called by the databound event
function CustomizeFilterMenu(args) {
    var parents = $(":radio").parent();
    if (!$(parents[0]).hasClass("RadioButtonFilterStyle")) {
        $(parents[0]).addClass("RadioButtonFilterStyle");
    }

    RebindGridState = true;

}

var GridStateTimer;

var RebindGridState = false;

$(document).ready(function () {
    $("#KendoGrid").removeAttr("hidden");
    kendo.ui.progress($("KendoGrid"), false);
    
    RebindGridState = false;
    GridStateTimer = setInterval(setGridState, 50);
});

 

The ideea is that every 50 miliseconds I check to see if the grid has finished loading its data. If so (RebindGridState is true), then apply the previous state and stop the timer. 

 

In my opinion, this solution is a hack, BUT, it get's the job done ... 

Is there a cleaner way to do this?

 

Thanks,

Vlad

0
Accepted
Boyan Dimitrov
Telerik team
answered on 22 Feb 2016, 01:00 PM

Hello Vlad,

 

My suggestion is to use one method in order the handler to be executed only once. Please refer to the Events article that provides some detailed information and sample code. 

 

Regards,
Boyan Dimitrov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Vlad
Top achievements
Rank 1
answered on 22 Feb 2016, 02:05 PM

Hello.

 

Thank you for your suggestion. I've read the Events section before posting the question. However, I found it a bit difficult to attach an event after "DataBound" that will fire one time only. I'll keep trying. Thank you.

0
fares
Top achievements
Rank 1
answered on 23 Jan 2020, 10:16 AM

Hello Vlad, 

Did you find a solution for the issue?

 

0
Alex Hajigeorgieva
Telerik team
answered on 27 Jan 2020, 09:12 AM

Hello, Fares,

Here is a runnable example for your reference:

https://dojo.telerik.com/@bubblemaster/AgOqOqUK

Since the one() method is used after the grid is created, set the autoBind property to false, attach the dataBound handler and then call the data source read() method:

 var grid = $("#grid").kendoGrid({
      autoBind: false,
}).data("kendoGrid");
                  
grid.one("dataBound", function(){
      kendo.alert("DataBound")
});
                  
grid.dataSource.read();

Kind Regards,
Alex Hajigeorgieva
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
Grid
Asked by
Vlad
Top achievements
Rank 1
Answers by
Vlad
Top achievements
Rank 1
Boyan Dimitrov
Telerik team
fares
Top achievements
Rank 1
Alex Hajigeorgieva
Telerik team
Share this question
or