EJ2 Treegrid: Duplicate Rows

I am having a weird issue with the tree grid and a remote datasource.  It has taken forever to get the grid to display correctly just because how the data is, but none the less, its finally working except for some reason it is duplicating the rows when rendered.  The data looks like when you expand the company which has id of 0:

{

"result": [

{

"id": 1138,

"lor_order": 0,

"display_name": "Craig",

"reports_to": 0,

"has_children": 1,

"team_name": "Networking Team",

"report_order": 1,

"roles": "team_lead"

},

{

"id": 1141,

"lor_order": 0,

"display_name": "Paul",

"reports_to": 0,

"has_children": 1,

"team_name": "Software Team",

"report_order": 1,

"roles": "office_lead,team_lead"

},

{

"id": 1160,

"lor_order": 7,

"display_name": "Joel",

"reports_to": 0,

"has_children": 0,

"team_name": "",

"report_order": 1,

"roles": null

}

]

}

The grid code is:


 var treeGridObj_dataManager = new ej.data.DataManager({
            url: '/wp-json/lor/v1/Team/list',
            crudUrl: '/wp-json/lor/v1/Team/crud',
            adaptor: new ej.data.UrlAdaptor(),
            crossDomain: true,
            headers: [{"X-WP-Nonce": "<?=$nonce?>"}]
        });

       var reportsTo_dataManager = new ej.data.DataManager({
            url: '/wp-json/lor/v1/Team/ReportsTo/list',
            adaptor: new ej.data.UrlAdaptor(),
            crossDomain: true,
            headers: [{"X-WP-Nonce": "<?=$nonce?>"}]
        });

       var treeGridObj = new ej.treegrid.TreeGrid({
        dataSource: treeGridObj_dataManager,
        idMapping: 'id',
        parentIdMapping: 'reports_to',
        height: 500,
        treeColumnIndex: 1,
        allowPaging: false,
        editSettings: { allowEditing: true, allowAdding: false, allowDeleting: false, mode: 'Dialog' },
        toolbar: ['Edit','Update','Cancel'],
        columns: [
            { field: 'id', headerText: 'ID', isPrimaryKey: true, visible: false },
            { field: 'team_name', headerText: 'Team Name', textAlign: 'Left' },
            { field: 'reportsTo', headerText: 'Reports To', textAlign: 'Left', dataSource: reportsTo_dataManager, foreignKeyField: 'id', foreignKeyValue: 'display_name', width:1, },
            { field: 'display_name', headerText: 'Employee Name', textAlign: 'Left', allowEditing: false,  },
            { field: 'roles', headerText: 'Role', textAlign: 'Left',  edit: {
                    create: function(){
                        elem = document.createElement('input');
                        return elem;
                    },
                    read: function() {
                        return roleMultiSelect.value;
                    },
                    destroy: function() {
                        roleMultiSelect.destroy();
                    },
                    write: function(args){
                        roleMultiSelect = new ej.dropdowns.MultiSelect({
                            dataSource: roles,
                            mode: 'CheckBox',
                            showSelectAll: true,
                            fields: {text: 'text', value: 'value'},
                            floatLabelType: 'Always', placeholder: 'Role',
                            value: (args.rowData[args.column.field])?args.rowData[args.column.field].split(','):[],
                        });
                    roleMultiSelect.appendTo(elem);
                    }
                },
            },
            { field: 'report_order', headerText: 'Report BEFORE Members', textAlign: 'Center', clipMode: 'EllipsisWithTooltip',  editType: 'booleanedit', type: 'boolean', displayAsCheckBox: true },
            { field: 'lor_order', headerText: 'Display Order', textAlign: 'Center', editType: 'numericedit', edit: {params:{format: 'N0', decimals:0, step: 1, min: 1},}, },
        ],
        queryCellInfo: function(args){            
            if(!args.data.roles && args.column.field=='report_order'){
                args.cell.querySelector('.e-checkbox-wrapper.e-css').style.visibility="hidden";
            }
        },
        actionComplete: function(args){
            switch(args.requestType){
                case 'beginEdit':
                    args.dialog.headerContent.innerText = 'Edit '+args.rowData.display_name;
                    break;
                case 'save':
                    this.refresh();
                    break;
            }
        },
    });

    treeGridObj.appendTo('#grid');


This is what is rendered:


As you can see, the teams get duplicated with the one individual.  They all are indented correctly the first time, but the second set is not indented.  Any thoughts as to what is wrong?


5 Replies

MA Mark March 24, 2022 02:26 AM UTC

Ok, I figured out what is happening. When it loads, it is loading all 4 but only displaying the company. Then when you expand it, it adds the 3 more inset to the company which is right.

Edit: So if I return just the company on initial load, nothing displays, so I can't even get it to where they need to expand it to make the query. Help please, lol!

Edit2:  What is super interesting is dumping beforeRowDatabound clearly shows the data but rowDatabound never fires.


{

  "query": {

    "subQuery": null,

    "isChild": false,

    "distincts": [],

    "queries": [

      {

        "fn": "onWhere",

        "e": {

          "isComplex": false,

          "field": "reports_to",

          "operator": "equal",

          "value": null,

          "ignoreCase": false

        }

      }

    ],

    "key": "",

    "fKey": "",

    "expands": [],

    "sortedColumns": [],

    "groupedColumns": [],

    "params": [

      {

        "key": "IdMapping",

        "value": "id"

      }

    ],

    "lazyLoad": [],

    "isCountRequired": true

  },

  "xhr": {},

  "count": 1,

  "result": [

    {

      "id": 0,

      "lor_order": 0,

      "display_name": "",

      "team_name": "The Group",

      "roles": null,

      "report_order": true,

      "has_children": true

    }

  ],

  "request": "POST",

  "actual": {

    "count": 1,

    "result": [

      {

        "id": 0,

        "lor_order": 0,

        "display_name": "",

        "team_name": "The Group",

        "roles": null,

        "report_order": true,

        "has_children": true

      }

    ],

    "query": "SELECT option_value FROM wp_options WHERE option_name = '_transient_mepr_migrating' LIMIT 1"

  },

  "actionArgs": {},

  "name": "beforeDataBound",

  "cancel": true

}



MA Mark March 24, 2022 06:25 AM UTC

Ok, I got this working, BUT there is NO WAY this is right. By adding the below, it causes the row to show and then I just had to set hasChildMapping and then the expandy icon shows up:


beforeDataBound: function(args){
console.log(args);
args.cancel=false;
},


Edit: Not working again and I have no clue why.  What I do know, is the double issue is the same in that when it loads the child, it also is loads their children as well in a separate call but is hiding them, so when you expand, it shows what already exists and then makes another data call and appends duplicate data in the wrong spot.



PS Pon Selva Jeganathan Syncfusion Team March 24, 2022 01:55 PM UTC

Hi Mark, 
 
Thanks for contacting syncfusion forum. 
 
Based on your query, you are facing the issue(duplicate rows) while expanding the record in remote data binding. And based on your shared code snippet, you are using a foreign key column. 
 
We suspect that the reported issue may be arise due to the foreign key column. Since, we don’t have the Foreign Key support in TreeGrid (i.e. the Foreignkey column dataSource which is separate from the TreeGrid dataSource). TreeGrid Databinding concept is of hierarchy relationship, we do not provide in-built support for foreignkey datasource.  
 
In order to display the ForeignKey column in TreeGrid, we have used queryCellInfo event of TreeGrid. Please refer to the below help documentation for more information, 
 
For remote data: 
 
Using remoteData to TreeGrid, by default Tree Grid parent rows have been rendered with collapsed stateWhen a root node is expanded, its child nodes are rendered and are cached locally, such that on consecutive expand/collapse actions on root node, the child nodes are loaded from the cache instead from the remote server. 
 
We need to define hasChildMapping property for properly binding data to Tree Grid. The hasChildMapping property maps the field name in data source, that denotes whether current record holds any child records. This is useful internally to show expand icon while binding child data on demand. 
 
Please refer to the below documentation, 
https://ej2.syncfusion.com/documentation/treegrid/data-binding/#remote-data 
 
Please refer to the below demo link, 
https://ej2.syncfusion.com/demos/#/material/treegrid/remote-data 
 
Please refer to the below sample, 
https://www.syncfusion.com/downloads/support/directtrac/general/ze/url_adaptor-315253293 
 
If it does not meet your requirement kindly share the below details, 
 
  1. Detail explanation of your issue
  2. Share the video demo of the issue
  3. Share the network tab details.
 
Kindly get back to us for further assistance. 
 
Regards,   
Pon selva   
 



MA Mark March 25, 2022 08:39 AM UTC

Well, I finally got it all working and I can say it had nothing to do with the foreign keys, because those actually work 100% with TreeGrid, so call it a feature not a bug I guess, lol. For whatever reason, regardless of the datasource, I had to have args.cancel in beforeDataBound.  Then I had to make certain the data returned is only for the query being passed as the caching you spoke of really didn't matter because if I return all rows or not on initial load, every time you expand a row, it makes another call to the DB and thats where the duplicates come in.  Noe



PS Pon Selva Jeganathan Syncfusion Team March 28, 2022 01:53 PM UTC

Hi Mark, 
 
Thanks for the update. 
 
We are glad to hear your query has been solved. 
 
Kindly get back to us for further assistance. 
 
Regards,   
Pon selva   


SIGN IN To post a reply.
Loader.
Up arrow icon