Save and retrieve grouped and sorted columns based on json data

Posted by: sneha.nagaruru on 9 April 2021, 5:51 am EST

  • Posted 9 April 2021, 5:51 am EST

    Hi Wijmo Team,

    I have JSON data with header, binding, groupindex, groupdirection, sortindex and sortdirection.
    groupindex and sortindex values starts from 0,1,2... if none it is -1.
    groupdirection, sortdirection values are 'ASC', 'DESC' and ''(none).

    Here is the json column data
    {binding: 'name',header: 'Name',visible: true, sortinex:'-1', sortdirection:'', groupindex:'1', groupdirection:'ASC'},
    {binding: 'userId',header: 'User ID', visible: true, sortinex:'-1', sortdirection:'', groupindex:'-1', groupdirection:''},
    {binding: 'jobTitleName', header: 'Job', visible: true, sortinex:'-1', sortdirection:'', groupindex:'0', groupdirection:'DESC'},
    {binding: 'team', header: 'Team', visible: true, sortinex:'1', sortdirection:'DESC', groupindex:'-1', groupdirection:''}
    {binding: 'age', header: 'Age', visible: true, sortinex:'0', sortdirection:'ASC', groupindex:'', groupdirection:''}

    Used Angular and typescript for the application.
    As per the requirement
    1. when grouping is done/dragged to a grouppanel, sorting ascending also should be added to the column and that sort will be termed as groupdirection and hierarchy of grouping termed as groupindex.
    2. Columns with only sorting are termed as sortindex and sortdirection.

    Whenever grouping or sorting is performed or removed json data should be updated and saved and grid should refresh with updated json data.
  • Replied 11 April 2021, 7:33 pm EST

    Hi Sneha,

    You may refer to the following which demonstrates how we could save/restore the JSON data:
    https://codesandbox.io/s/wijmo-angular-forked-5wctz?file=/src/app/app.component.ts
    To apply the sort when group is added, you may handle the collectionChanged event of grid.collectionView.groupDescriptions collection and add the sort description. Above shared sample also demonstrates this functionality.

    Regards
    Sharad
  • Replied 21 April 2021, 2:48 am EST

    Hi Sharad,

    In my code I have a grid.formatItem.addHandler to change the icons of expand/collapse of grouped columns due to which whenever the grouping is done grid.collectionView.collectionChanged.addHandler, grid.collectionView.groupDescriptions.collectionChanged.addHandler are not hitting. Is there any alternative tCan you please help me to proceed further.


    Also at the end of the initGrid I have added grid.onLoadedRows(grid); Is it required and what's the purpose of it?


    initGrid(grid: wjcGrid.FlexGrid) {
    grid.selectionMode = (this.toggleStatus) ? wjcGrid.SelectionMode.MultiRange : wjcGrid.SelectionMode.Row;
    grid.formatItem.addHandler((s, e) => {
    var row = s.rows[e.row];
    if (s.cells === e.panel && row instanceof wjcGrid.GroupRow) {

    var classToRemove =
    'wj-glyph-' + (row.isCollapsed ? 'right' : 'down-right');

    var classToAdd =
    'bento-icon-caret-' +
    (row.isCollapsed ? 'right-filled' : 'down-filled');
    var span = e.cell.querySelector('span.' + classToRemove) as HTMLElement;
    if (span) {
    wjcCore.removeClass(span, classToRemove);
    wjcCore.createElement(`<i class="${classToAdd}"></i>`, span);
    }
    }
    });

    //Handle drag and drop events
    grid.draggedColumn.addHandler((s, e) => {
    s.columns.forEach(col => {
    this.gridColumns.map(g => {
    if (col.binding == g.binding) {
    g.display_index = col.index;
    }
    });
    });
    this.savePreferences();
    });

    //handle resize column width.
    grid.resizedColumn.addHandler((s, e) => {
    s.columns.forEach(col => {
    this.gridColumns.map(g => {
    if (col.binding == g.binding) {
    g.width = col.width;
    }
    });
    });
    this.savePreferences();
    });

    grid.collectionView.collectionChanged.addHandler((s, e) => {
    // save data on sort/grouping
    if (e.action === wjcCore.NotifyCollectionChangedAction.Reset) {
    alert('grouped');
    }
    });

    grid.collectionView.groupDescriptions.collectionChanged.addHandler(
    (s, e) => {
    if (e.action === wjcCore.NotifyCollectionChangedAction.Add) {
    let grpDesc: any = e.item;
    let col = grid.columns.getColumn(grpDesc.propertyName);
    if (col.currentSort) {
    grid.collectionView.sortDescriptions.splice(
    col.currentSortIndex,
    1,
    new wjcCore.SortDescription(col.binding, true)
    );
    } else {
    grid.collectionView.sortDescriptions.push(
    new wjcCore.SortDescription(col.binding, true)
    );
    }
    }
    }
    );


    grid.onLoadedRows(grid);
    }


  • Replied 22 April 2021, 11:28 pm EST

    Hi Sneha,

    Using the formatItem event should not affect the event. Please share a small sample which replicates the issue so that we could further investigate the issue and assist you accordingly.

    Thank you
  • Replied 25 April 2021, 10:02 pm EST

    Hi Sharad,

    As per my understanding, On ngOnInit I'm passing the data as null when the initGrid is triggered, the grid.collectionView is undefined giving out an error and not registering the handlers for two of the events. So later when we do the grouping, the grid.collectioonView events are not triggered but the grid.formatItem is triggered.


    ngOnInit() {
    this.data=null;
    }

    //Loading the data to the grid based on user inputs.
    @Input() set filterCriteria(value) {
    if (value != undefined) {
    this.utilities = value;
    OnBindData();
    }

    //based on service call getting the data and assigning it to grid
    onBindData() {
    this.dataService.getGridData(this.utilities).subscribe((res) => {
    this.data = res;
    });
    }


    Error Image: 1. Error at initGrid 2. When EntityID is grouped Sorting is not getting added to that column


    Regards,
    Sneha
  • Replied 26 April 2021, 8:29 pm EST

    Hi Sharad,

    Any updates on it? Like how we have the grid.sortedColumn.addHandler, do we have any handler for the grid when a column is grouped?

  • Replied 26 April 2021, 8:39 pm EST

    Hi Sneha,

    Indeed passing the null parameter as the initial value is causing the issue. To fix the issue what you should do is pass an instance of collectionView with an empty array and then when data from the service is fetched assign it to the sourceCollection property of the collection view. Refer to the following code snippet:
    /* import wijmo core module */
    import * as wjCore from "@grapecity/wijmo";

    constructor(){
    /* empty collection view */
    this.data = new wjCore.CollectionView([]);
    /* you may bind collectionview event handlers to this collection view */
    }

    /* fetch data from service */
    onBindData() {
    this.dataService.getGridData(this.utilities).subscribe((res) => {
    this.data.sourceCollection = res;
    });
  • Replied 29 April 2021, 3:59 am EST

    Hi Sharad,

    I tried the suggested changes and I didn't get any errors but this time still the collectionview related events are not getting fired.

    Can we implement with a different approach like from point of GroupPanel. For sorting I have used grid.sortedcolumn.addhandler event which is working fine.
    Now I'm left with add or remove Grouping and adding sort to the grouped column.
    Please provide a solution asap.


    ngOnInit() {
    this.data=new wjCore.CollectionView([]);
    }

    //Loading the data to the grid based on user inputs.
    @Input() set filterCriteria(value) {
    if (value != undefined) {
    this.utilities = value;
    OnBindData();
    }

    //based on service call getting the data and assigning it to grid
    onBindData() {
    this.dataService.getGridData(this.utilities).subscribe((res) => {
    this.data = res;
    });
    initGrid(grid: wjcGrid.FlexGrid) {
    grid.selectionMode = (this.toggleStatus) ? wjcGrid.SelectionMode.MultiRange : wjcGrid.SelectionMode.Row;
    grid.sortedColumn.addHandler((s, e) => {
    s.columns.forEach(col => {
    this.gridColumns.map(g => {
    if (col.binding == g.binding) {
    g.sortdirection = (col.currentSort == "+" ? "Ascending" : col.currentSort == "-" ? "Descending" : "None");
    g.sortindex = col.currentSortIndex;
    // console.log("sorting column : " + col.binding + " col sort : " + col.currentSort + " -- col sort Index: " + col.currentSortIndex + "^^^Resulr :" + g.sortdirection + "/Index" + g.sortindex);
    }
    });
    });
    this.savePreferences();
    });
    grid.formatItem.addHandler((s, e) => {
    var row = s.rows[e.row];
    if (s.cells === e.panel && row instanceof wjcGrid.GroupRow) {

    var classToRemove =
    'wj-glyph-' + (row.isCollapsed ? 'right' : 'down-right');

    var classToAdd =
    'bento-icon-caret-' +
    (row.isCollapsed ? 'right-filled' : 'down-filled');
    var span = e.cell.querySelector('span.' + classToRemove) as HTMLElement;
    if (span) {
    wjcCore.removeClass(span, classToRemove);
    wjcCore.createElement(`<i class="${classToAdd}">[/i]`, span);
    }
    }
    });

    //Handle drag and drop events
    grid.draggedColumn.addHandler((s, e) => {
    s.columns.forEach(col => {
    this.gridColumns.map(g => {
    if (col.binding == g.binding) {
    g.display_index = col.index;
    }
    });
    });
    this.savePreferences();
    });

    //handle resize column width.
    grid.resizedColumn.addHandler((s, e) => {
    s.columns.forEach(col => {
    this.gridColumns.map(g => {
    if (col.binding == g.binding) {
    g.width = col.width;
    }
    });
    });
    this.savePreferences();
    });

    grid.collectionView.collectionChanged.addHandler((s, e) => {
    // save data on sort/grouping
    if (e.action === wjcCore.NotifyCollectionChangedAction.Reset) {
    alert('grouped');
    }
    });

    grid.collectionView.groupDescriptions.collectionChanged.addHandler(
    (s, e) => {
    if (e.action === wjcCore.NotifyCollectionChangedAction.Add) {
    let grpDesc: any = e.item;
    let col = grid.columns.getColumn(grpDesc.propertyName);
    if (col.currentSort) {
    grid.collectionView.sortDescriptions.splice(
    col.currentSortIndex,
    1,
    new wjcCore.SortDescription(col.binding, true)
    );
    } else {
    grid.collectionView.sortDescriptions.push(
    new wjcCore.SortDescription(col.binding, true)
    );
    }
    }
    }
    );
    grid.onLoadedRows(grid);
    }
    }


    Thanks & Regards,
    Sneha Nagaruru
  • Replied 29 April 2021, 6:45 pm EST

    From the code snippet I could observe that inside the onBindData method you are changing the this.data value with new array, it will cause the grid to create a new collection view, You need to change the following code
    //based on service call getting the data and assigning it to grid
    onBindData() {
    this.dataService.getGridData(this.utilities).subscribe((res) => {
    this.data = res;
    });

    to
    //based on service call getting the data and assigning it to grid
    onBindData() {
    this.dataService.getGridData(this.utilities).subscribe((res) => {
    this.data.sourceCollection = res;
    });
  • Replied 29 April 2021, 11:27 pm EST

    Hi Sharad,

    I'm not able to see the data in the grid with this.data.sourceCollection, grouping events are firing. Can you please check mywork-grid.component.html and mywork-grid.component.ts files and suggest the required changes. I'm passing the data to the grid in getGridColumnsCompleted() method and I have tried itemsSource as data and data.sourceCollection in flexgrid (HTML).

    gridColumns have the column properties and in the Html, we are looping the grid columns

    <wj-flex-grid #flexGrid class="bento-flex-grid has-row-hover" [class.list-grid]="isListGrid" [itemsSource]="data"
    [stickyHeaders]="true" [showMarquee]="true" [showSort]="true" (initialized)="initGrid(flexGrid)"
    [headersVisibility]="'Column'" [allowSorting]="'MultiColumn'" (selectionChanged)="onSelectionChanged()">
    <wj-flex-grid-column *ngFor="let col of gridColumns" [header]="col.header" [binding]="col.binding"
    [visible]="col.visible" [width]="col.width" [isReadOnly]="true">
    </wj-flex-grid-column></wj-flex-grid>

    For further details, please check the zip file contents



    Thanks & Regards,
    Sneha Nagaruru

  • Replied 29 April 2021, 9:24 pm EST

    Files

    mywork-grid.component.zip
  • Replied 2 May 2021, 7:45 pm EST

    Hi Sneha,

    In the attached component.ts file, I noticed that the following code line #505
    this.data.sourceCollection = new wjcCore.CollectionView(griddData, {
    pageSize: this.pagenationInfo.pageSize,
    });

    the sourceCollection property expects the data to be of array type, so changing the above code to following should fix the issue:
    this.data.sourceCollection = griddData;
    this.data.pageSize = this.pagenationInfo.pageSize;


    If the issue persists, please share a working sample that we could execute and debug at our end.

    Regards
Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels