Hi Telerik,
I have a Grid with persistence implemented exactly like described here => https://demos.telerik.com/aspnet-core/grid/persist-state
Sequence of actions:
1) Start application
2) Reorder columns
3) Save state
4) Reorder columns again for testing purpose => another reorder, not reordering back to the original order
5) Load state
=> everything is working fine, order is back to saved state
But:
1) Start application
2) Reorder columns
3) Save state
4) Close app/browser
5) Run app again => original order is back
6) Load state
=> The order of the columns is changing to the saved state, but the Grid hangs in an infinite loop loading the data
Grid:
Html.Kendo().Grid<OalViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.OrderNumber).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Width(100).Title("Auftrag").HtmlAttributes(new { style = "text-align: center" }).Locked(true);
columns.Command(command => { command.Edit(); }).Width(150).HtmlAttributes(new { style = "text-align: center" }).Locked(true);
columns.Bound(p => p.Split).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Width(80).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.OrderType).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Width(80).Title("Art").HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.OutletIndicator).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Width(80).Title("FIL").HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.AcceptanceDate).Format("{0: dd.MM.yyyy}").Filterable(ftb => ftb.Cell(y => y.Template("datePicker"))).Title("Angenommen am").Width(150).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.AcceptedBy).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Title("Angenommen von").Width(150).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.CreatedBy).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Title("Erstellt von").Width(125).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.Make).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Title("Marke").Width(80).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.Status).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Width(80).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.InvoiceDate).Format("{0: dd.MM.yyyy}").Filterable(ftb => ftb.Cell(y => y.Template("datePicker"))).Title("RG-Dat.").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.InvoicePrintedOk).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Title("RG-Druck").Width(80).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.LicenseNumber).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Title("Kennz.").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.CustomerNumber).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Title("KD-Nr").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.Customer).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).Title("KD").Width(100);
columns.Group(x => x
.Title("Integration").HeaderHtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F;" })
.Columns(info =>
{
info.Bound(p => p.ExactDescription).Width(250).HtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F; text-align: left" }).HeaderHtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F" }).Title("Genaue Beschreibung");
info.Bound(p => p.PlannedCompletionDate).Format("{0: dd.MM.yyyy}").Filterable(ftb => ftb.Cell(y => y.Template("datePicker"))).HtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F; text-align: center" }).HeaderHtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F" }).Title("Fertigstellung").Width(100);
info.Bound(p => p.PlannedSettlementDate).Format("{0: dd.MM.yyyy}").Filterable(ftb => ftb.Cell(y => y.Template("datePicker"))).HtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F; text-align: center" }).HeaderHtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F" }).Title("RG-Stellung").Width(100);
info.Bound(p => p.OrderAvailable).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).HtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F; text-align: center" }).HeaderHtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F" }).Title("Auftrag vorhanden?").Width(100);
info.Bound(p => p.OrderBillable).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).HtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F; text-align: center" }).HeaderHtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F" }).Title("Auftrag abrechenbar?").Width(100);
//info.Bound(p => p.OrderStatus).Filterable(ftb => ftb.Multi(true).Search(true).CheckAll(true)).HtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F" }).HeaderHtmlAttributes(new { style = "border-color:#642A3F; border: 1pt solid #642A3F" }).Title("Auftrags-Status?").Width(100);
}));
columns.Bound(p => p.OrderValueTotal).Format("{0:C}").ClientFooterTemplate("#= kendo.format('{0:c}', sum)#").Title("Auftragswert").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.Tax).Format("{0:C}").ClientFooterTemplate("#= kendo.format('{0:c}', sum)#").Title("Steuer").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.OrderValueTotalNoTax).Format("{0:C}").ClientFooterTemplate("#= kendo.format('{0:c}', sum)#").Title("Auftragswert o. MwSt.").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.OrderValueVehicle).Format("{0:C}").ClientFooterTemplate("#= kendo.format('{0:c}', sum)#").Title("Auftragswert Fzg").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.OrderValueEquipment).Format("{0:C}").ClientFooterTemplate("#= kendo.format('{0:c}', sum)#").Title("Auftragswert Zubehör").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.OrderValueFlatRateUnits).Format("{0:C}").ClientFooterTemplate("#= kendo.format('{0:c}', sum)#").Title("Auftragswert AW").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.OrderValueParts).Format("{0:C}").ClientFooterTemplate("#= kendo.format('{0:c}', sum)#").Title("Auftragswert Teile").Width(100).HtmlAttributes(new { style = "text-align: center" });
columns.Bound(p => p.OrderValueSublets).Format("{0:C}").ClientFooterTemplate("#= kendo.format('{0:c}', sum)#").Title("Auftragswert Sonstiges").Width(100).HtmlAttributes(new { style = "text-align: center" });
})
.ColumnResizeHandleWidth(20)
.ColumnMenu()
.Sortable()
.Scrollable(s => s.Height("auto"))
.Filterable()
.Reorderable(reorder => reorder.Columns(true))
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("CustomPopupOAL"))
.ToolBar(toolbar =>
{
toolbar.Custom().Text("Import DMS").IconClass("k-icon k-i-file-excel").HtmlAttributes(new { id = "customCommand" });
toolbar.Excel();
toolbar.Pdf();
toolbar.Custom().Text("Ansicht speichern").IconClass("k-icon k-i-export").HtmlAttributes(new { id = "save" });
toolbar.Custom().Text("Ansicht laden").IconClass("k-icon k-i-import").HtmlAttributes(new { id = "load" });
toolbar.Search();
})
.Pdf(pdf => pdf.AllPages(true))
.Excel(excel => excel.AllPages(true))
.Pageable(p => p
.ButtonCount(5)
.PageSizes(new[] { 10, 25, 50 })
.Refresh(true)
.Input(true)
)
.HtmlAttributes(new { style = "height:600px;" })
.DataSource(dataSource => dataSource
.SignalR()
.AutoSync(false)
.PageSize(10)
.Aggregates(aggregates =>
{
aggregates.Add(p => p.OrderValueTotal).Sum();
aggregates.Add(p => p.Tax).Sum();
aggregates.Add(p => p.OrderValueTotalNoTax).Sum();
aggregates.Add(p => p.OrderValueVehicle).Sum();
aggregates.Add(p => p.OrderValueEquipment).Sum();
aggregates.Add(p => p.OrderValueFlatRateUnits).Sum();
aggregates.Add(p => p.OrderValueParts).Sum();
aggregates.Add(p => p.OrderValueSublets).Sum();
} )
.Transport(tr => tr
.Promise("hubStart")
.Hub("hub")
.Client(c => c
.Read("read")
.Create("create")
.Update("update")
.Destroy("destroy"))
.Server(s => s
.Read("read")
.Create("create")
.Update("update")
.Destroy("destroy")))
.Schema(schema => schema
.Model(model =>
{
model.Id(order => order.OrderNumber);
model.Field(p => p.OrderNumber).Editable(false);
model.Field(p => p.Split).Editable(false);
model.Field(p => p.OrderType).Editable(false);
model.Field(p => p.OutletIndicator).Editable(false);
model.Field(p => p.AcceptanceDate).Editable(false);
model.Field(p => p.AcceptedBy).Editable(false);
model.Field(p => p.CreatedBy).Editable(false);
model.Field(p => p.Make).Editable(false);
model.Field(p => p.Status).Editable(false);
model.Field(p => p.InvoiceDate).Editable(false);
model.Field(p => p.InvoicePrintedOk).Editable(false);
model.Field(p => p.LicenseNumber).Editable(false);
model.Field(p => p.CustomerNumber).Editable(false);
model.Field(p => p.Customer).Editable(false);
}
)
)
)
Javascript:
<script>
$(document).ready(function () {
var grid = $("#grid").data("kendoGrid");
$("#save").click(function (e) {
e.preventDefault();
localStorage.kendogridoptions = kendo.stringify(grid.getOptions());
});
$("#load").click(function (e) {
e.preventDefault();
var options = localStorage.kendogridoptions;
if (options) {
grid.setOptions(JSON.parse(options));
}
});
});
</script>
Note: In the javascript code above you will see a difference to the demo code. I Changed
localStorage["kendo-grid-options"] = kendo.stringify(grid.getOptions());
to
localStorage.kendogridoptions = kendo.stringify(grid.getOptions());
Because I researched the problem and found a lot of sources telling that the proper/better way of accessing the localstorage would be by using "localStorage.<VALUE-NAME>".
But first I tried with the exaxt demo code, also running into the same problem.
What am I doing wrong? After restarting the app and loading the state, the order of the colums is changed, but the grid is unable to load the data.
Is it because I use SignalR binding? I need realtime updates as many users are working in the same grid at the same time, and this is only working with SignalR, correct?
Appreciate any tips!
Thanks
Thomas