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

Preserve grid state in a cookie - Razor syntax

9 Answers 288 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Developer
Top achievements
Rank 1
Developer asked on 21 Aug 2013, 11:42 AM
Hi, i am trying to follow this guide and rewrite it to the Razor syntax:
Preserve grid state in cookie example.

The difference from my code and the example code is that they use AutoBind: false.
I cant use that in Razor because i initialize the data into the model when the view is rendered.

Another difference is that the example uses schema: syntax, don't think i need that when using razor, Am i correct?

Here is my razor code:

01.@model IEnumerable<Backend.ViewModel.ViewSalon>
02.<div id="salonDetail">
03. 
04.    @(Html.Kendo().Grid(Model)
05.          .Name("Grid")
06.          .Columns(c =>
07.                   {
08.                       c.Bound(m => m.Id).Width(30);
09.                       c.Bound(m => m.Name).Width(110).HtmlAttributes(new { @class = "customerName" });
10.                       c.Bound(m => m.Telephone).Width(100);
11.                       c.Bound(m => m.ContactPerson).Width(100);
12.                       c.Bound(m => m.City).Width(50);
13.                       c.Bound(m => m.StatusId).HtmlAttributes(new { @class = "statusid" }).Hidden();
14.                       c.Bound(m => m.Kundnr).Width(50);
15. 
16.                   })     
17.                  .Scrollable()
18.                  .DataSource(dataSource => dataSource       
19.                  .Ajax()               
20.                  .ServerOperation(false)  
21.                )
22. 
23.                  .ColumnMenu()
24.                  .Reorderable(reorder => reorder.Columns(true))
25.                  .Resizable(resize => resize.Columns(true))
26.                  .Selectable(selectable => selectable.Mode(GridSelectionMode.Multiple))
27.                  .Sortable()
28.                  .Filterable()
29.                  .Events(events => events.Change("onChange").DataBound("onDataBound").DataBinding("onDataBinding"))
30.                  .HtmlAttributes(new { style = "height: 408px" })
31.          )
32.</div>
01.@* Loads cookie support *@
03. 
04.<script type="text/javascript">
05.     //START: *** Save grid state ***
06.     
07.    function onDataBound(e) {
08.        var grid = $(this).data("kendoGrid");
09.        var dataSource = this.dataSource;
10. 
11.        var state = kendo.stringify({
12.            page: dataSource.page(),
13.            pageSize: dataSource.pageSize(),
14.            sort: dataSource.sort(),
15.            group: dataSource.group(),
16.            filter: dataSource.filter()
17.        });
18. 
19.        $.cookie("customerState", state);
20. 
21.        if ($.cookie('customerRows')) {
22.            $.each(JSON.parse($.cookie('customerRows')), function () {
23.                var item = dataSource.get(this);
24.                var row = grid.tbody.find('[data-uid=' + item.uid + ']');
25.                row.addClass('k-state-selected');
26.            });
27.        }
28.    }
29.     
30.    function onChange(e) {
31.        var grid = $(this).data("kendoGrid");
32.        var ids = grid.select().map(function () {
33.            return grid.dataItem($(this)).Id;
34.        }).toArray();
35.        $.cookie('customerRows', JSON.stringify(ids));
36.    }
37. 
38.    function parseFilterDates(filter, fields) {
39.        if (filter.filters) {
40.            for (var i = 0; i < filter.filters.length; i++) {
41.                parseFilterDates(filter.filters[i], fields);
42.            }
43.        }
44.        else {
45.            if (fields[filter.field].type == "date") {
46.                filter.value = kendo.parseDate(filter.value);
47.            }
48.        }
49.    }
50.     
51.    function onDataBinding() {
52.       
53.    }
54. 
55.    $(document).ready(function () {
56.        var grid = $('#Grid').data("kendoGrid");
57. 
58.        var state = JSON.parse($.cookie("customerState"));
59.        if (state) {
60.            if (state.filter) {
61.                parseFilterDates(state.filter, grid.dataSource.options.schema.model.fields);
62.            }
63.            grid.dataSource.query(state);
64.        }
65.        else {
66.            grid.dataSource.read();
67.        }
68.         
69.        // END: *** Save grid state ***
70.</script>

 

9 Answers, 1 is accepted

Sort by
0
Daniel
Telerik team
answered on 23 Aug 2013, 11:13 AM
Hello,

The code looks correct. The only thing that I noticed and that could cause problems is calling  the read method without a read action being specified.
Regarding the AutoBind option and the schema:

  1. The data should be bound via an Ajax request if you wish to prevent the initial binding. The binding cannot be prevented with the AutoBind option if the data is bound on the server.
  2. The schema is automatically generated by the wrappers based on the bound model.

Regards,
Daniel
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Developer
Top achievements
Rank 1
answered on 26 Aug 2013, 12:28 PM
var item = dataSource.get(this);
'item' get's undefined when i run this.
'this' returns the value of  the id('s) from cookie.

0
Daniel
Telerik team
answered on 27 Aug 2013, 05:43 PM
Hello again,

In order for the get method to return an item for the model ID, you should specify the ID field with the DataSource Model:

.DataSource(dataSource => dataSource      
          .Ajax()              
          .ServerOperation(false
          .Model(model => model.Id(m => m.Id))
  )
Regards,
Daniel
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Developer
Top achievements
Rank 1
answered on 29 Aug 2013, 11:19 AM
Ty Daniel, that solved the item problem.

But this was harder than i expected ;)
I now have a problem retrieving the state's, the only state that isn't undefined is sort, wye is that?

Is there someone that have the time to test this script out with the razor syntax and then tell me the answer?

Another question, wye can't i use var grid = $(this).data("kendoGrid"); instead of var grid = $('#customerGrid').data("kendoGrid"); to make it more dynamic?

Thanks in advantage!

@(Html.Kendo().Grid(Model.Salons)
          .Name("customerGrid")
          .Columns(c =>
                   {
                       c.Bound(m => m.Id).Width(30);
                       c.Bound(m => m.Name).Width(110).HtmlAttributes(new { @class = "customerName" });
                       c.Bound(m => m.Telephone).Width(100);
                       c.Bound(m => m.ContactPerson).Width(100);
                       c.Bound(m => m.City).Width(50);
                       c.Bound(m => m.StatusId).HtmlAttributes(new { @class = "statusid" }).Hidden();
                       c.Bound(m => m.Kundnr).Width(50);
                   })
          .Scrollable()
          .DataSource(dataSource => dataSource       
              .Ajax()               
              .ServerOperation(false)  
              .Model(model => model.Id(m => m.Id))
          )
          .ColumnMenu()
          .Reorderable(reorder => reorder.Columns(true))
          .Resizable(resize => resize.Columns(true))
                  .Selectable(selectable => selectable.Mode(GridSelectionMode.Multiple))
          .Sortable()
          .Filterable()
                  .Events(events => events.Change("onChangeSalon").DataBound("onDataBoundSalon"))
          .HtmlAttributes(new { style = "height: 408px; width: 500px;" })
          )
$(document).ready(function () {
        var grid = $('#customerGrid').data("kendoGrid");
         
        var state = JSON.parse($.cookie("customerState"));
 
        if (state) {
            if (state.filter) {
                parseFilterDates(state.filter, grid.dataSource.options.schema.model.fields);
            }
            grid.dataSource.query(state);
        }
        else {
            grid.dataSource.read();
        }
});
function onDataBoundSalon(e) {
        var grid = $('#customerGrid').data("kendoGrid");
        var dataSource = grid.dataSource;
 
        //group is the only one that doesen't get undefined.
        var state = kendo.stringify({
            page: dataSource.page(),
            pageSize: dataSource.pageSize(),
            sort: dataSource.sort(),
            group: dataSource.group(),
            filter: dataSource.filter()
        });
      
        $.cookie("customerState", state);
 
        if ($.cookie('customerRows')) {
            // Selects selected row.
            $.each(JSON.parse($.cookie('customerRows')), function () {
                // this - returns id of salon inside cookie.
                var item = dataSource.get(this);
                var row = grid.tbody.find('[data-uid=' + item.uid + ']');
                row.addClass('k-state-selected');
            });
        }
    }
function parseFilterDates(filter, fields) {
            if (filter.filters) {
                for (var i = 0; i < filter.filters.length; i++) {
                    parseFilterDates(filter.filters[i], fields);
                }
            }
            else {
                if (fields[filter.field].type == "date") {
                    filter.value = kendo.parseDate(filter.value);
                }
            }
        }
function onChangeSalon() {
        var grid = $('#customerGrid').data("kendoGrid");
 
        var ids = grid.select().map(function () { return grid.dataItem($(this)).Id }).toArray();
         
        $.cookie('customerRows', JSON.stringify(ids));
}
0
Daniel
Telerik team
answered on 02 Sep 2013, 11:04 AM
Hello,

The values are undefined because the initial binding is not prevented and the values are overridden in the databound event. You should bind the data with an Ajax request and prevent the initial binding or do not set the state the first time the event is triggered. Another option is to bind the handler via JavaScript in the document ready event:

$(document).ready(function () {
    var grid = $('#customerGrid').data("kendoGrid");    
    var state = JSON.parse($.cookie("customerState"));
 
    if (state) {
        if (state.filter) {
            parseFilterDates(state.filter, grid.dataSource.options.schema.model.fields);
        }
        grid.dataSource.query(state);
    }
    else {
        grid.dataSource.read();
    }
     
    grid.bind("dataBound", onDataBoundSalon);
});

"this" cannot be used to get the grid because the event is bound to the document and not the grid. Thus the context in the handler will be the document. If you wish to reuse the code then you could create a separate function which is called in the context of the grid object or the object is passed as parameter.

Regards,
Daniel
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Mariusz
Top achievements
Rank 1
answered on 25 Oct 2013, 09:54 AM
In my case, when I preserve a date filter, the date is decreasing by one day each time page is loaded. I'm using code from your example, mentioned by Dick.
0
Daniel
Telerik team
answered on 29 Oct 2013, 08:36 AM
Hello,

The problem could be caused by the automatic conversion to UTC performed by the Date.prototype.toJSON method. You could either override the method so that the date is serialized with the same time or create a new Date from the serialized string:

filter.value = new Date(filter.value);
which should convert the date back to local. Regards,
Daniel
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Dan
Top achievements
Rank 1
answered on 12 Nov 2013, 07:46 PM
Hi
I was able to get the same sample working for our site and its fine, however we are also using the Column Menu and would like to persist the visibility state of each column as well. I am able to save the state off in the cookie but I cant get the grid to update and show or hide the columns after reading it back in.

Here is how I am trying to do it.
first add event handler for both show and hide column
function onColumnVisibilityChange(e) {
    var grid = $('#ListAccountsGrid').data("kendoGrid");
    var dataSource = grid.dataSource;
    var columnState = getColumnState();
    var state = JSON.parse($.cookie("ListAccountsGridState"));
 
    state = kendo.stringify({
        page: dataSource.page(),
        pageSize: dataSource.pageSize(),
        sort: dataSource.sort(),
        group: dataSource.group(),
        filter: dataSource.filter(),
        columnState: columnState
    });
 
    $.cookie("ListAccountsGridState", state);
}
 
function getColumnState() {
    var columnState = {};
    var grid = $('#ListAccountsGrid').data("kendoGrid");
    var columns = grid.columns;
 
    $(columns).each(function (i) {
        columnState[this.field] = this.hidden ? true : false;
    });
 
    return columnState;
}

I then read it back in - I tried in both the ready function with no luck and in the onDataBound with no luck. I also tried updating the grid both by setting the columns directly and also by setting via the grids options object - neither seemed to work.
function onDataBound(e) {
    var grid = $('#ListAccountsGrid').data("kendoGrid");
    var dataSource = grid.dataSource;
 
    // read back in to get Column State
    var state = JSON.parse($.cookie("ListAccountsGridState"));
    var columns = grid.options.columns;
 
    if (state) {
        $(columns).each(function (i) {
            this.hidden = state.columnState[this.field];
        });
    }
     
    var columnState = getColumnState();
 
    // save back out updated datasource settings
    var state = kendo.stringify({
        page: dataSource.page(),
        pageSize: dataSource.pageSize(),
        sort: dataSource.sort(),
        group: dataSource.group(),
        filter: dataSource.filter(),
        columnState: columnState
    });
 
    $.cookie("ListAccountsGridState", state);
}
 
 
 
$(document).ready(function () {
    var grid = $('#ListAccountsGrid').data("kendoGrid");
 
    // not working so commented out - maybe grid options are overwritten so attempt to set column visibility in onDataBound instead
    //var state = JSON.parse($.cookie("ListAccountsGridState"));
    //var columns = grid.options.columns;
     
    if (state) {
        //$(columns).each(function (i) {
        //    this.hidden = state.columnState[this.field];
        //});
        grid.dataSource.query(state);
    } else {
        grid.dataSource.read();
    }
});

Any help would be greatly appreciated
Thanks
Dan



0
Dan
Top achievements
Rank 1
answered on 13 Nov 2013, 05:45 PM

I think I was overthinking this - there is already a method on the Grid to show hide columns that I overlooked so I updated my code to simply iterate the grid and call one of the two based on the state that is stored in the cookie.

Maybe not the best way but it works. Here is my updated code if anyone else needs it.

function onColumnVisibilityChange(e) {
    var grid = $('#ListAccountsGrid').data("kendoGrid");
    var dataSource = grid.dataSource;
    var columnState = getColumnState();
    var state = JSON.parse($.cookie("ListAccountsGridState"));
 
    state = kendo.stringify({
        page: dataSource.page(),
        pageSize: dataSource.pageSize(),
        sort: dataSource.sort(),
        group: dataSource.group(),
        filter: dataSource.filter(),
        columnState: columnState
    });
 
    $.cookie("ListAccountsGridState", state);
}
 
function getColumnState() {
    var columnState = {};
    var grid = $('#ListAccountsGrid').data("kendoGrid");
    var columns = grid.columns;
 
    $(columns).each(function (i) {
        columnState[this.field] = this.hidden ? true : false;
    });
 
    return columnState;
}
 
$(document).ready(function () {
    var grid = $('#ListAccountsGrid').data("kendoGrid");
 
    var state = JSON.parse($.cookie("ListAccountsGridState"));
    var columns = grid.columns;
     
    // columnState.FieldName = (hidden)True || False
    if (state) {
        $(columns).each(function (i) {
            if (state.columnState[this.field]) {
                grid.hideColumn(i);
            }
            if (this.hidden && !state.columnState[this.field]) {
                grid.showColumn(i);
            }
        });
        grid.dataSource.query(state);
    } else {
        grid.dataSource.read();
    }
});
Tags
Grid
Asked by
Developer
Top achievements
Rank 1
Answers by
Daniel
Telerik team
Developer
Top achievements
Rank 1
Mariusz
Top achievements
Rank 1
Dan
Top achievements
Rank 1
Share this question
or