Búsqueda de sitios web

typescript - Kendo Sortable/Integración - Grid - No se ordena después de una actualización específica


Tengo una cuadrícula Kendo según el código siguiente

 @(Html.Kendo().Grid<ReportCompetencyViewModel>()
     .Name("listGrid")
     .BindTo(Model.ReportCompetency.OrderBy(x => x.DisplayOrder))
     .Columns(columns =>
     {
         columns.Bound(c => c.Code).ClientHeaderTemplate("Code");
         columns.Bound(c => c.DisplayName).ClientHeaderTemplate("Description");
         columns.Bound(c => c.IEC).ClientHeaderTemplate("IEC");
         columns.Bound(c => c.Active)

             .ClientTemplate("#if(Active) {# <i class='fas fa-check'></i>  # } else {# <i class='fas fa-times'></i> #} #")
             .ClientHeaderTemplate("Active")
             .HtmlAttributes(new { @class = "text-center" })
             .Width(100);

     })
     .Pageable(pageable => pageable
         .Refresh(true)
         .PageSizes(true)
         .ButtonCount(5))
     .Sortable()
     .Filterable()
     .Groupable()
     .NoRecords(n => n.Template("<p>There are no records to display.</p>"))
     .HtmlAttributes(new { style = "width:100%;" })
     .Selectable(selectable => selectable
         .Mode(GridSelectionMode.Single)
         .Type(GridSelectionType.Row))
     .Events(events => events
         .Change("lu.onChange")
     )
     .Pageable(p =>
     {
         p.PageSizes(new[] { 5, 10, 30, 50, 100 });
     })
     .DataSource(dataSource => dataSource
         .Ajax()
         .Group(g => g.Add(x => x.IEC))
         .PageSize(50)
         .ServerOperation(false)
         .Read(r => r.Action("RefreshCompetenciesGridData", "ReportLookup").Data("lu.sendAntiForgery"))

     )
)

Tengo un parcial que también tiene un elemento que se puede ordenar, como se muestra a continuación.

@(Html.Kendo().Sortable()
          .For($"#{@Model.GridId}")
          .Filter("table > tbody > tr")
          .Cursor("move")
          .PlaceholderHandler("sg.placeholder")
          .ContainerSelector($"#{Model.GridId} tbody")
          .Events(events => events.Change("sg.onChange"))
)

El evento onchange es

 onChange = (e: any) => {
        var grid: kendo.ui.Grid = $("#" + this.gridId).data("kendoGrid"),
            skip = grid.dataSource.skip(),
            oldIndex = e.oldIndex + skip,
            newIndex = e.newIndex + skip,
            data = grid.dataSource.data(),
            dataItem = grid.dataSource.getByUid(e.item.data("uid"));
        grid.dataSource.remove(dataItem);
        grid.dataSource.insert(newIndex, dataItem);

        console.log(newIndex);

        if (this.showSaveNotification && $("#" + this.warningDivId).length) {
            $("#" + this.warningDivId).slideDown();
            this.showSaveNotification = false;
        }
    }

El elemento ordenable funciona muy bien, la mayor parte del tiempo.

Al realizar un reorden, abrir una ventana de kendo y realizar una acción de guardado, la cuadrícula se actualiza con los datos actualizados en una clase de TypeScript según el código a continuación.

save = (model: any) => {
var _self = this;

var girdOrderArray = new Array();

if ($("#grid-reorder-warning").length && $("#grid-reorder-warning").is(":visible")) {
    var grid = $("#" + this.girdName).data("kendoGrid");
    var dataItems = grid.dataItems() as any;
    $.each(dataItems,
        (idx: number, dataItem) => {
            var di = idx + 1;
            var id = dataItem.id === undefined ? dataItem.Id : dataItem.id; // Changing the display order appears to also change the dataItem from Id to id. 
            girdOrderArray.push({ Id: id, DisplayOrder: di });
        });

}

var da = new Tmsp.AjaxDataAccessLayer(Tmsp.Enums.AjaxCallType.Post,
    Tmsp.Enums.AjaxDataType.Json,
    this.saveUrl,
    JSON.stringify(model),
    "application/json; charset=utf-8",
    { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
    true, true);

da.ajaxCall(data => {

    _self.closeWindow();

    if ($("#grid-reorder-warning").is(":visible")) {
        grid.dataSource.read().then(() => {
            var dataItems = grid.dataItems();
            var arr = new Array() as any;
            $.each(dataItems,
                (idx, dataItem: any) => {
                    var id = dataItem.Id === null ? dataItem.id : dataItem.Id;
                    var gridOrderObj = jQuery.grep(girdOrderArray,
                        function (gridOrderObj: any) { return gridOrderObj.Id == id });
                    dataItem.set("DisplayOrder", gridOrderObj[0].DisplayOrder);
                });

            grid.dataSource.sort({ field: "DisplayOrder", dir: "Desc" });
        });

    } else {
        _self.refreshGrid();
    }

    return false;

}, (xhr, status, errorThrown) => {
    console.log(xhr);
    console.log(status);
    console.log(errorThrown);
});

return false;
}   

Esto guarda y reordena la cuadrícula en consecuencia por el DisplayOrder, lo cual es genial y lo que necesito. Sin embargo, cuando intento reordenar cualquier otra cosa después de esto, el elemento reordenado me da el nuevo índice, pero en realidad no se cambia en la cuadrícula.

Sin embargo, si actualizo la cuadrícula por otros medios, la reordenación funciona perfectamente.

Entonces, mi pregunta, ya que necesito mantener el orden de visualización como estaba antes de guardar, ¿cómo logro esto?

Cosas que he probado

  • Actualizando el orden de visualización en la cuadrícula actualizada: causa sospechosa del problema.
  • Creó un nuevo controlador que devuelve el parcial e inicializa el control nuevamente - Sin efecto
  • Restablecer el uid (no es una opción preferida, pero pensé en intentarlo para ver si era específico del uid). - Sin efecto

Respuesta #1

¡Ah ja!!!

He encontrado la respuesta y Telerik no facilita encontrar cómo hacer las cosas.

Usando el enlace que tengo aquí https://docs.telerik.com/kendo-ui/controls/interactivity/sortable/how-to/persist-order-in-localstorage he podido encontrar el código que necesito para persistir el estado.

Creo que en uno de mis intentos la semana pasada estaba realmente bastante cerca, aunque no perfecto.

así es como se ve ahora el evento on change

onChange = (e: any) => {
    var grid: kendo.ui.Grid = $("#" + this.gridId).data("kendoGrid"),
    skip = grid.dataSource.skip(),
    oldIndex = e.oldIndex + skip,
    newIndex = e.newIndex + skip,
    data = grid.dataSource.data(),
    dataItem = grid.dataSource.getByUid(e.item.data("uid"));
    grid.dataSource.remove(dataItem);
    grid.dataSource.insert(newIndex, dataItem);

    console.log(newIndex);
    localStorage.setItem("sortableData", kendo.stringify(data)); //set the updated in local storage

 if (this.showSaveNotification && $("#" + this.warningDivId).length) {
        $("#" + this.warningDivId).slideDown();
        this.showSaveNotification = false;
    }
}

la nueva línea aquí es

localStorage.setItem("sortableData", kendo.stringify(data)); //set the updated in local storage

la nueva cuadrícula de guardar y actualizar se ve así

saveNewOrder = () => {

var model = new Array();
var grid: kendo.ui.Grid = $("#" + this.gridId).data("kendoGrid");
var _self = this;
var dataItems = grid.dataItems() as any;
$.each(dataItems,
    (idx : number, dataItem) => {
        var di = idx + 1;
        var id = dataItem.Id === null ? dataItem.id : dataItem.Id;
        model.push({ Id: id , DisplayOrder: di});
    });

var da = new AjaxDataAccessLayer(Tmsp.Enums.AjaxCallType.Put,
    Tmsp.Enums.AjaxDataType.Json,
    this.saveUrl,
    JSON.stringify(model),
    "application/json; charset=utf-8",
    { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
    true,
    true);

da.ajaxCall(data =>{

    _self.refreshGridOrder();

}, (xhr, textStatus, errorThrown) => {
    ////console.log(xhr);
    ////console.log(textStatus);
    ////console.log(errorThrown);
 });

}

refreshGridOrder = () => {
    var grid = $("#" + this.gridId).data("kendoGrid");


    grid.dataSource.read().then(() => {
        var data = JSON.parse(localStorage.getItem("sortableData"));
        grid.dataSource.data(data);
        $("#" + this.warningDivId).slideUp();
        this.showSaveNotification = true;
 });
}

Lo otro a recordar es que, como esto se utiliza desde múltiples ubicaciones, también se debe borrar el almacenamiento local en el momento en que el documento esté listo.