Blazor TreeGrid On demand loading problems

My datasource is an ObservableColletion and I'm trying to load child data using the Expanded="OnRowExpanded" event of the treegrid as a way of loading dynamic data on demand when the parent node is expanded. I've set the  HasChildMapping="IsParent" property to true so the arrow will show even without child data, but when I initially load data into the collection, the parent node is always expanded (despite having no child items), which means I must first collapse and then reopen the parent node to trigger the Expanded event. If I set EnableCollapseAll="true" then when I click the arrow the parent node opens momentarily triggering the expanded event and then closes on it's own. How do I add empty parent nodes with arrows that are collapsed when rendered? I've tried to use the ExpandStateMapping="IsExpanded" property set to false for the parent item, but it doesn't seem to do anything. I also see the ExpandStateMapping takes a string property rather than a bool which doesn't make sense to me. Thanks for any help. 


5 Replies

FS Farveen Sulthana Thameeztheen Basha Syncfusion Team November 23, 2020 04:18 PM UTC

Hi Tim, 

Thanks for contacting Syncfusion Support. 

Query#:- How do I add empty parent nodes with arrows that are collapsed when rendered? 
 
We have checked your query and  In order to achieve Load OnDemand concept using Observable data we suggest you to use customBinding concept of the TreeGrid. Using CustomBinding, all root nodes has been rendered  in collapsed state at initial load. HasChildMapping property is enough to determine whether it is parent node or not and there is not necessary to use ExpandStateMapping. The custom data binding can be performed in the Tree Grid component by providing the custom adaptor class and overriding the Read or ReadAsync method of the DataAdaptor abstract class. 
 
Refer to the documentation Link for more information:- 

Refer to the code below:- 

<SfTreeGrid @ref="treeGrid" TValue="TreeData.BusinessObject" AllowPaging="true" AllowFiltering="true" 
            HasChildMapping="isParent" IdMapping="TaskId" ParentIdMapping="ParentId" 
            TreeColumnIndex="1" AllowSorting="true"> 
    <SfDataManager AdaptorInstance="@typeof(CustomAdaptor)" Adaptor="Adaptors.CustomAdaptor"></SfDataManager> 
    <TreeGridPageSettings PageSize="1"></TreeGridPageSettings> 
 
    <TreeGridColumns> 
        <TreeGridColumn Field="TaskId" HeaderText="Task ID" IsPrimaryKey="true" Width="80" TextAlign="TextAlign.Right"></TreeGridColumn> 
          .   .   . 
   </TreeGridColumns> 
</SfTreeGrid> 
 
@code{ 
      
    public static SfTreeGrid<TreeData.BusinessObject> treeGrid { get; set; } 
    public ObservableCollection<TreeData.BusinessObject> TreeData = new ObservableCollection<TreeData.BusinessObject >();     
     
    protected override void OnInitialized() 
    { 
        TreeGridData = TreeData.GetSelfDataSource(); 
    } 
 
 
    // Implementing custom adaptor by extending the DataAdaptor class 
    public class CustomAdaptor : DataAdaptor 
    { 
        // Performs data Read operation 
        public override object Read(DataManagerRequest dm, string key = null) 
        { 
             
            IEnumerable<TreeData.BusinessObject> DataSource = TreeGridData; 
            if (dm.Search != null && dm.Search.Count > 0) 
            { 
                // Searching 
                DataSource = DataOperations.PerformSearching(DataSource, dm.Search); 
            } 
            if (dm.Sorted != null && dm.Sorted.Count > 0) 
            { 
                // Sorting 
                DataSource = DataOperations.PerformSorting(DataSource, dm.Sorted); 
            } 
 
            if (dm.Where != null && dm.Where.Count > 0) 
            { 
                 
               DataSource = DataOperations.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator); 
           } 
 
            int count = DataSource.Cast<TreeData.BusinessObject>().Count(); 
            if (dm.Skip != 0) 
            { 
                //Paging 
                DataSource = DataOperations.PerformSkip(DataSource, dm.Skip); 
            } 
            if (dm.Take != 0) 
            { 
                DataSource = DataOperations.PerformTake(DataSource, dm.Take); 
            } 
           return dm.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource; 
 
        } 
 
    } 
} 


Please get back to us if you need any further assistance on it. 

Regards, 
Farveen sulthana T 



TI Tim November 24, 2020 06:01 AM UTC

That seems like swatting a fly with a shovel....just to get a parent node to render collapsed. Either way:

when I add data like:
 
TreeData.Add(new SelfReferenceData { TaskID = 1, Catagory = "project", Name = projname, Properties = props.ToString(), IsParent = true });

the root parent node shows up, but when I use the OnRowExpandedAsync to append child data:

TreeData.Add(new SelfReferenceData { TaskID = 2, Catagory = "project", Name = "some name", Properties = props.ToString(), IsParent = true, ParentID = 1 });

the data shows up when expanded but, the parent node automatically collapses itself and won't stay open.


<Syncfusion.Blazor.TreeGrid.SfTreeGrid @ref="treeGrid" GridLines="Syncfusion.Blazor.Grids.GridLine.Both" TValue="TreeGridComponent.Data.SelfReferenceData" Height="659px" HasChildMapping="IsParent" EnableCollapseAll="false" LoadChildOnDemand="true" AllowFiltering="true" AllowTextWrap="true" IdMapping="TaskID" ParentIdMapping="ParentID" TreeColumnIndex="1" EnableVirtualization="false">
                                <TreeGridEvents TValue="TreeGridComponent.Data.SelfReferenceData" Expanded="OnRowExpandedAsync" RowDataBound="OnRowDataBound"></TreeGridEvents>
                                <TreeGridFilterSettings HierarchyMode="FilterHierarchyMode.Parent" Type="Syncfusion.Blazor.TreeGrid.FilterType.Excel"></TreeGridFilterSettings>
                                <Syncfusion.Blazor.Data.SfDataManager AdaptorInstance="@typeof(CustomAdaptor)" Adaptor=" Syncfusion.Blazor.Adaptors.CustomAdaptor"></Syncfusion.Blazor.Data.SfDataManager>
                                <Syncfusion.Blazor.TreeGrid.TreeGridColumns>
                                    <Syncfusion.Blazor.TreeGrid.TreeGridColumn Field="TaskId" Visible="false" HeaderText="Task ID" Width="1" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Center"></Syncfusion.Blazor.TreeGrid.TreeGridColumn>
                                    <Syncfusion.Blazor.TreeGrid.TreeGridColumn Field="Catagory" HeaderText="Catagory" Width="200" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Left"></Syncfusion.Blazor.TreeGrid.TreeGridColumn>
                                    <Syncfusion.Blazor.TreeGrid.TreeGridColumn Field="Workorder" HeaderText="Workorder" Width="200" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Left"></Syncfusion.Blazor.TreeGrid.TreeGridColumn>
                                    <Syncfusion.Blazor.TreeGrid.TreeGridColumn Field="ActivityID" HeaderText="ActID" Width="150" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Left"></Syncfusion.Blazor.TreeGrid.TreeGridColumn>
                                    <Syncfusion.Blazor.TreeGrid.TreeGridColumn Field="Name" HeaderText="Name" Width="500" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Left"></Syncfusion.Blazor.TreeGrid.TreeGridColumn>
                                    <Syncfusion.Blazor.TreeGrid.TreeGridColumn Field="Abbr" HeaderText="Abbr" Width="100" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Left"></Syncfusion.Blazor.TreeGrid.TreeGridColumn>
                                    <Syncfusion.Blazor.TreeGrid.TreeGridColumn Field="Properties" HeaderText="Properties" Width="1000" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Left"></Syncfusion.Blazor.TreeGrid.TreeGridColumn>
                                </Syncfusion.Blazor.TreeGrid.TreeGridColumns>
                            </Syncfusion.Blazor.TreeGrid.SfTreeGrid>



@code{
    public static SfTreeGrid<SelfReferenceData> treeGrid { get; set; }
    public static List<SelfReferenceData> TreeData { get; set; }


protected override void OnInitialized()
        {
            TreeData = SelfReferenceData.GetTree();
        }

}






TI Tim November 24, 2020 07:33 AM UTC

namespace TreeGridComponent.Data
{
    public class SelfReferenceData
    {
        public static List tree = new List();
        public int? TaskID { get; set; }
        public int? ParentID { get; set; }
        public bool? IsParent { get; set; }
        public string Catagory { get; set; }
        public string Workorder { get; set; }
        public string ActivityID { get; set; }
        public string Name { get; set; }
        public string Abbr { get; set; }
        public string Properties { get; set; }
       
       



        public SelfReferenceData() { }
        public static List GetTree()
        {
            return tree;
        }
    }
}



 public class CustomAdaptor : DataAdaptor
    {
        // Performs data Read operation
        public override object Read(DataManagerRequest dm, string key = null)
        {
            IEnumerable DataSource = plancode.Pages.Index.TreeData;
            if (dm.Search != null && dm.Search.Count > 0)
            {
                // Searching
                DataSource = DataOperations.PerformSearching(DataSource, dm.Search);
            }
            if (dm.Sorted != null && dm.Sorted.Count > 0)
            {
                // Sorting
                DataSource = DataOperations.PerformSorting(DataSource, dm.Sorted);
            }
            if (dm.Where != null && dm.Where.Count > 0)
            {
                // Filtering
                DataSource = DataOperations.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);
            }
            int count = DataSource.Cast().Count();
            if (dm.Skip != 0)
            {
                //Paging
                DataSource = DataOperations.PerformSkip(DataSource, dm.Skip);
            }
            if (dm.Take != 0)
            {
                DataSource = DataOperations.PerformTake(DataSource, dm.Take);
            }
            return dm.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource;
        }
    }



TI Tim November 24, 2020 08:38 AM UTC

I figured out what was going on. I was calling treeGrid.Refresh() in the Expanded event and it was causing the parent row to collapse immediately after open. I moved my code to the Expanding event and with the observablecollection there's no need to call the Refresh method. Now the parent renders collapsed and loads while expanding.


FS Farveen Sulthana Thameeztheen Basha Syncfusion Team November 25, 2020 11:31 AM UTC

Hi Tim, 
 
We hope that your problem has been resolved. Please get back to us if you need any further assistance on it. We are happy to assist you. 
 
Regards, 
Farveen sulthana T 


Loader.
Up arrow icon