SfTreeGrid error expand mapping

Hello i've got a Syncfusion 19.2 license.

Im trying to build a SfTreeGrid component like this

but i've got the problem that when collapse the 00.1-AFA, and then expand the 01 - Edificio A.


The 001. -AFA automatically exands.


My code looks like this




I know that HasChildMapping is only for remote origin,

but that should have relation with the problem that im getting.


I have to put the HasChildMapping even thought the source is not remove because i'm loading the

root child when I click on one item of the GridColumn root.


If i dont put the ExpandStateMapping in the component SfTreeGrid,

then the when the component loads, it already appears has expanded has default.


And the some weird behaviour but opposite happends to the elements, all of them collapse when I expand any other element.



Also the  EnableVirtualization works extremely buggy.

you have to click multiple times to expand/collapse the items.


17 Replies 1 reply marked as answer

MA Miguel Angel Morales Gonzalez December 16, 2021 04:01 PM UTC

<SfTreeGrid DataSource="@ItemsOrigin"
            Height="600px"
            AllowTextWrap="true"
            IdMapping="Id"
            @ref="RefSfTreeGrid"
            ParentIdMapping="ParentId"
            ExpandStateMapping="@nameof(ZoneMappingEditableListItem.Expanded)"
            HasChildMapping="HasChildren"
>
    <TreeGridColumns>
        <TreeGridColumn Width="60%" Field="@nameof(ZoneMappingEditableListItem.MantTestZoneCode)"
                        HeaderText="@Strings.MantTest" >
            <Template>
                @{
                    var item = ItemsOriginCopy.FirstOrDefault(x => x.Id == ((ZoneMappingEditableListItem)context).Id);
                }


                @if (Loading.Any(x => x.Key == ((ZoneMappingEditableListItem)item).Id)
                && Loading[((ZoneMappingEditableListItem)item).Id]
                && ((ZoneMappingEditableListItem)item).HasChildren)
                {
                    <LoadingView IsLoading="@Loading[((ZoneMappingEditableListItem)item).Id]" />
                }
                else
                {
                    <div id="@(((ZoneMappingEditableListItem)item).Id)" @onclick="async () => {

                            if(!ParentsAlreadyLoaded.Any(x=>x==item.Id))
                            {
                                ParentsAlreadyLoaded.Add(item.Id);

                                Loading.Add(item.Id,true);

                                var zoneMappingsEditableList =
                                    (await Client.GetZoneMappingMantTestChildAsync(
                                        new GetZoneMappingMantTestChild()
                                                    {
                                                        ParentId=item.Id
                                                    })).ZoneMappingsEditable;
                                if(zoneMappingsEditableList.Mappings.Any())
                                {
                                    var childs=zoneMappingsEditableList.Mappings.Where(x=>!ItemsOriginCopy.Any(y=>x.Id==y.Id));


                                                                    var listToAdd = new List<ZoneMappingEditableListItem>();
                                    foreach(var child in childs)
                                    {
                                      var mapped=ZoneMappingsList.Mappings.FirstOrDefault(x=>x.Id==child.Id);


                                                if(mapped!=null)
                                                {
                                                 listToAdd.Add(
                                                            new ZoneMappingEditableListItem(){
                                                                AccountId=mapped.AccountId,
                                                                Id=mapped.Id,
                                                                MantTestZoneCode=mapped.MantTestZoneCode,
                                                                IrisZoneCode=mapped.IrisZoneCode,
                                                                Expanded=child.Expanded,
                                                                HasChildren=child.HasChildren,
                                                                MantTestZoneName=child.MantTestZoneCode,
                                                                ParentId=child.ParentId});
                                                }
                                                else
                                                {
                                                  listToAdd.Add(new ZoneMappingEditableListItem(){
                                                                             AccountId=child.AccountId,
                                                                             Expanded=child.Expanded,
                                                                             HasChildren=child.HasChildren,
                                                                             Id=child.Id,
                                                                             IrisZoneCode=child.IrisZoneCode,
                                                                             MantTestZoneCode=child.MantTestZoneCode,
                                                                             MantTestZoneName=child.MantTestZoneName,
                                                                             ParentId=child.ParentId});
                                                }
                                    }


                                    listToAdd.ForEach(x=>ItemsOrigin=ItemsOrigin.Append(x));

                                    ItemsOriginCopy.AddRange(listToAdd);
                                    await RefSfTreeGrid.CallStateHasChangedAsync();
                                    await RefSfTreeGrid.RefreshAsync();
                                }
                                Loading[item.Id]=false;
                            }
                        ;}
                    ">
                        <label> @item.MantTestZoneCode</label>
                    </div>
                }
            </Template>
        </TreeGridColumn>
    </TreeGridColumns>
</SfTreeGrid>
@code {

    SfTreeGrid<ZoneMappingEditableListItem> RefSfTreeGrid;
    [Parameter]
    public ZoneMappingsList? ZoneMappingsList { get; set; }

    [Parameter]
    public ICollection<ZoneMappingEditableListItem>? ItemsParam { get; set; }

    [Parameter]
    public IEnumerable<string>? ZoneCodes { get; set; }

    public EventCallback<IEnumerable<ZoneMappingEditableListItem>> SourceChanged { get; set; }

    [Parameter]
    public EventCallback<ZoneMappingEditableListItem> OnMappingChange { get; set; }

    public IEnumerable<ZoneMappingEditableListItem>? ItemsOrigin { get; set; }

    public List<ZoneMappingEditableListItem> ItemsOriginCopy { get; set; }

    public Dictionary<string, bool> Loading { get; set; } = new Dictionary<string, bool>();

    public List<string> ParentsAlreadyLoaded { get; set; } = new List<string>();

    public bool isLoading { get; set; }

    public List<TreeGridSortColumn> Sort { get; set; }

    protected override Task OnInitializedAsync()
    {

        ItemsOrigin = new List<ZoneMappingEditableListItem>(ItemsParam.Where(x=>x?.MantTestZoneCode!=null));

        ItemsOrigin.ForEach(x => x.HasChildren = true);

        ItemsOriginCopy = new List<ZoneMappingEditableListItem>(ItemsOrigin);
        return base.OnInitializedAsync();
    }

    public EventCallback<IEnumerable<ZoneMappingEditableListItem>> DataSourceChanged { get; set; }

    protected void SelectedCarsChanged(string id, Microsoft.AspNetCore.Components.ChangeEventArgs e)
    {
        ItemsOriginCopy.FirstOrDefault(x => x.Id == id).IrisZoneCode = (string)e.Value;
        OnMappingChange.InvokeAsync(ItemsOriginCopy.FirstOrDefault(x => x.Id == id));
    }
}



FS Farveen Sulthana Thameeztheen Basha Syncfusion Team December 16, 2021 04:13 PM UTC

Hi Miguel, 

Thanks for contacting Syncfusion Support. 

Query#:- i've got the problem that when collapse the 00.1-AFA, and then expand the 01 - Edificio A. 
The 001. -AFA automatically expands. 
 
We have checked your reported problem using ExpandStateMapping property but we are unable to replicate the problem at our end.  

 
Note:- Also it is not recommended to use HasChildMapping property as it is used only for RemoteData. Refer to the documentation link:- 

So we need some more additional details to find the cause of the issue. Share us the following details. 

  1. Remove HasChildMapping property and check whether the issue replicates or not.
  2. If possible replicate it in the above sample and revert us back.
  3. Video Demo to replicate the issue.

Query#:- Also the  EnableVirtualization works extremely buggy.you have to click multiple times to expand/collapse the items. 
 
Also share details of the issue you have faced with EnableVirtualization with ExpandStateMapping property. Based on the details we will validate the issue and proceed further. 

Regards, 
Farveen sulthana T 



MA Miguel Angel Morales Gonzalez replied to Farveen Sulthana Thameeztheen Basha December 16, 2021 05:25 PM UTC

Hello,

Im going to attach a rar file that contains multiple videos, a photo and the code file.

In some of the videos I changed the component properties.


in the video 

17-36-38_Trim there's no HasChildMapping.


Thanks for your support, hope you can help me.


Also I had to make a DataSource Copy because it keept givin an error bcs the source was beign modified,in the onclick event

So had to make the copy to avoid the error


PD:

I saw your video,

now im going to watch the example


Also the syncfusion forum comments are buggy


I'm using .net5



Attachment: 20211216_252b97f8.rar



FS Farveen Sulthana Thameeztheen Basha Syncfusion Team December 18, 2021 07:33 AM UTC

Hi Miguel, 

We are quite unclear of your reported Error from your video demo. Also, we are unable to replicate the issue on Expand/Collapse action. So share us the detailed Explanation of your reported problem with ExpandStateMapping and replicate the issue in the attached sample on previous update  
and revert us back. Based on the details we will proceed further. 

Also the syncfusion forum comments are buggyà Share more details for this problem. 

Regards, 
Farveen sulthana T 



MA Miguel Angel Morales Gonzalez December 20, 2021 08:42 AM UTC

Hello Farveen,


I've replicated the problem using your project.


I've attached two videos, one of which has virtualization enabled.


about

Also the syncfusion forum comments are buggy
I'm going to take some time to share the details as im a little bit busy.

Thank you

Attachment: 20211220_993fdf9a.rar


MA Miguel Angel Morales Gonzalez replied to Farveen Sulthana Thameeztheen Basha December 20, 2021 08:45 AM UTC

As you can see, there are items that are expanding when the should't if the IsExpanded was correct.


Or maybe its just that I dont know how to use the control correctly 



MA Miguel Angel Morales Gonzalez December 20, 2021 09:06 AM UTC

In the video that i've attach you cannot see my mouse cursor,

I'm trying to find a screen recorder in which you


PD:here it is

the is quite long 10-02-0, it has the virtualization bug


In 10-03-40 its easy to spot the exanded bug


PD2:

I cannot attach a file wtf in Edit



MA Miguel Angel Morales Gonzalez December 21, 2021 07:46 AM UTC

Here its attached the new videos with the cursor showing


Attachment: 20211220_2294d664.rar


Thank you


PD1:

I've seen that there's already open a thread were the virtualization bug is dealed with.


But its not the same that I first encountered in which I had a lot of troube exapanding the elements while using virtualization.

But on the recent videos im only showing you the same bug that its already beign handled.

https://www.syncfusion.com/feedback/27709/virtualization-support-with-expandstatemapping


Nevertheless, lets focus on the bug that some elements expand when they shouldn't,


PD2:

Is there a possibility that you enable an HasChildMapping with local data?

For my sceneraio it would be ideal

Because I want to load the child on onclick.

Without that property I can't have the "expand" "collapse" symbol in some cases.

I will have to do an ugly workaround if I cant use that property with local data

like loading an empty child and after click removing it and loading the good child data, so I can show the "expand" "collapse" symbol



FS Farveen Sulthana Thameeztheen Basha Syncfusion Team December 21, 2021 03:49 PM UTC

Hi Miguel, 

Thanks for your details. 

We will check your reported problem from your attached videos and provide you further details by on or before 23rd December, 2021. Until then we appreciate your patience. 

Regards, 
Farveen sulthana T 



MA Miguel Angel Morales Gonzalez replied to Farveen Sulthana Thameeztheen Basha December 21, 2021 04:47 PM UTC

Hello Farveen,


You're welcome.


Okay, I will be watting for your answer on 23rd December.


Thanks





FS Farveen Sulthana Thameeztheen Basha Syncfusion Team December 22, 2021 03:39 PM UTC

Hi Miguel,  

Thanks for your update. We will update you the details by tomorrow. 

Regards,
Farveen sulthana T 



FS Farveen Sulthana Thameeztheen Basha Syncfusion Team December 24, 2021 05:08 AM UTC

Hi Miguel, 

We appreciate your patience. 

Query#1:- lets focus on the bug that some elements expand when they shouldn't, 

#Without using Virtualization:- 

We have checked your reported problem from your provided sample. In that sample, you have used Template column to append child records upon clicking the Expand Icon. At that time you have used RefreshAsync method to re-render the TreeGrid with these changes. So the TreeGrid has been re-rendered with original state (expanded/Collapsed) based on ExpandStateMapping property. 

When using ExpandStateMapping, only during the initial render the expanded/collapsed state will be maintained by the field property assigned to ExpandStateMapping in datasource of the treegrid. After subsequent expand/collapse actions will not be updated in datasource. This is the default behavior. To update the field value in datasource, it can be done through expanded/collapsed event. So while on refreshing it has been changed as like Initial render. 

#With Virtualization and ExpandStateMapping:- 
 
As you have mentioned, we have logged feature request regarding this. 

Query#2:- Is there a possibility that you enable an HasChildMapping with local data? 
 
No, it is not feasible to use HasChildMapping property for LocalData.  

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

Regards, 
Farveen sulthana T 



MA Miguel Angel Morales Gonzalez January 3, 2022 12:52 PM UTC

Hello  Farveen,

Thanks for your reply.


I will think about your reply and try to apply it to my project.

Will contact you again to keep you updated if I make it work as I want.


Thanks



PS Pon Selva Jeganathan Syncfusion Team January 5, 2022 02:56 PM UTC

Hi Miguel,  
 
Thanks for the update. 
 
We will wait to hear from you. 
Regards,    
Pon selva   


MA Miguel Angel Morales Gonzalez January 10, 2022 03:32 PM UTC

@inject IrisAppStrings AppStrings
@inject MantTestStrings Strings
@inject IrisMantTestClient Client
@using IrisTenantWeb.MantTest.ZonesMapping.Pages
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.TreeGrid;
@using System.Collections.ObjectModel
@inject IJSRuntime JsRuntime




Height="480px"
@ref="sfTreeGrid"
AllowResizing="true"
AllowSorting="true"
IdMapping="Id"
ParentIdMapping="ParentId"
AllowTextWrap="true"
HasChildMapping="HasChildren"
ExpandStateMapping="Expanded">
@if (Show)
{


Direction="Syncfusion.Blazor.Grids.SortDirection.Ascending" />







HeaderText="@Strings.MantTest" IsPrimaryKey=true>






Field="@nameof(ZoneMappingEditableListItem.IrisZoneCode)"
AllowEditing="true" AllowAdding="true"
HeaderText="@Strings.IrisZone">





OnChange="(x)=>{SelectedCarsChanged((item as ZoneMappingEditableListItem).Id,x);}"
AllowCustom=true DataSource="@ZoneCodes" Enabled="true" />






AllowEditing="true" AllowAdding="true"
HeaderText="Mappings">







}





@code {
private async Task ConvertArray(string ariaLabel)
{
await JsRuntime.InvokeAsync("functionName", ariaLabel);
}
SfTreeGrid sfTreeGrid;


public bool Show { get; set; } = true;


[Parameter]
public ZoneMappingsList? ZoneMappingsList { get; set; }


[Parameter]
public ICollection? ItemsParam { get; set; }


[Parameter]
public IEnumerable? ZoneCodes { get; set; }


[Parameter]
public EventCallback OnMappingChange { get; set; }


public ObservableCollection? ItemsOrigin { get; set; }


public Dictionary Loading { get; set; } = new Dictionary();


public List ParentsAlreadyLoaded { get; set; } = new List();


public bool isLoading { get; set; }


public List Sort { get; set; }


protected override Task OnInitializedAsync()
{
ItemsOrigin = new ObservableCollection(ItemsParam);


return base.OnInitializedAsync();
}


public async Task Collapsing(RowCollapsingEventArgs args)
{


}
public async Task Collapse(RowCollapsedEventArgs args)
{


ItemsOrigin.FirstOrDefault(x => x.Id == args.Data.Id).Expanded = false;
Show = true;
StateHasChanged();


await ConvertArray(args.Data.MantTestZoneCode);
}


public async Task Expanded(RowExpandedEventArgs args)
{


var serviceTagDetails = args.Data;
if (!ParentsAlreadyLoaded.Any(x => x == serviceTagDetails.Id))
{


ParentsAlreadyLoaded.Add(serviceTagDetails.Id);


Loading.Add(serviceTagDetails.Id, true);


var zoneMappingsEditableList =
(await Client.GetZoneMappingMantTestChildAsync(
new GetZoneMappingMantTestChild()
{
ParentId = serviceTagDetails.Id
})).ZoneMappingsEditable;
Show = false;
StateHasChanged();


if (zoneMappingsEditableList.Mappings.Any())
{
var childs = zoneMappingsEditableList.Mappings.Where(x => !ItemsOrigin.Any(y => x.Id == y.Id));


foreach (var child in childs)
{
var mapped = ZoneMappingsList.Mappings.FirstOrDefault(x => x.Id == child.Id);


if (mapped != null)
{
ItemsOrigin.Add(
new ZoneMappingEditableListItem()
{
AccountId = mapped.AccountId,
Id = mapped.Id,
MantTestZoneCode = mapped.MantTestZoneCode,
IrisZoneCode = mapped.IrisZoneCode,
Expanded = child.Expanded,
HasChildren = child.HasChildren,
MantTestZoneName = child.MantTestZoneName,
ParentId = child.ParentId
});


}
else
{
ItemsOrigin.Add(child);
}
}
}


ItemsOrigin.FirstOrDefault(x => x.Id == ((ZoneMappingEditableListItem)args.Data).Id).Expanded = true;


Loading[serviceTagDetails.Id] = false;


isLoading = false;




}
ItemsOrigin.FirstOrDefault(x => x.Id == args.Data.Id).Expanded = true;
Show = true;
StateHasChanged();
await ConvertArray(args.Data.MantTestZoneCode);
}


protected void SelectedCarsChanged(string id, Microsoft.AspNetCore.Components.ChangeEventArgs e)
{
ItemsOrigin.FirstOrDefault(x => x.Id == id).IrisZoneCode = (string)e.Value;


OnMappingChange.InvokeAsync(ItemsOrigin.FirstOrDefault(x => x.Id == id));
}
}

Finally i've been able to make the SfTreeGrid work withouth exception.

I tried managing the expand and collapse state with the events that you metion,

udating the values of the datasource so that the state is the correct one.


As you can see in the code I have had to use

 HasChildMapping="HasChildren" ExpandStateMapping="Expanded"

because its the only way I can achieve the kind of behaviour that I want.


Nevertheless, I must say that the thing that has solved for me all the problems that I was facing

is the if(show) code.


The component SfTreeGrid even withouth using the HasChildMapping, very often it keept giving lots of error

saying .AddListener has already an event etc etc.


Its a blazor/syncfusion error, nothing to do with my code.


But using the show and making blazor rendering again the component I was able to stop those kind of errors apearing.


I really tryied to use multiple methods of SFtreeGrid to make it "refresh" or generate again so all the errors stop appearing.


But none of the methods offered by syncfusion were able to make the SfTreeGred work nicely.



MA Miguel Angel Morales Gonzalez January 10, 2022 04:31 PM UTC

Here's a video of it working correctly.


Like i was saying it really was impossible to make it work correctly withouth using the if(show)

I really tried all syncfusion methods to "refresh" or "update" etc.


idk if its a blazor error or syncfusion "xxx eventlistener already isxxx.." something like that.


But now its working okay thanks to the show code



PD1:

The javascript function is to set focus to the selected item.

Because when i make show=false or true and update de status.

The components renders again an loses the "focus" of the selected item in the tree so i've done something like this


function functionName(name) {

var newName = name.concat(" Column Header MantTest");

var m = "";

m = m.concat(newName);


setTimeout(() => document.querySelector("[aria-label=\'" + m + "'\]").focus(), 500);


}


the code is quite dirty and the variable and methods name dont have much sense.

i have yet to clean the code but that doesn't matter now



Attachment: 161739_1e26e4b7_b1f1ea9d.rar



FS Farveen Sulthana Thameeztheen Basha Syncfusion Team January 11, 2022 03:41 PM UTC

Hi Miguel, 

Thanks for your update. We are glad to know that your reported problem has been resolved. 

Also as we have mentioned earlier, we have logged feature task relates to Virtualization in combination with ExpandStateMapping. Also we suggest to use HasChildMapping for RemoteData alone to avoid any further problems. In case of without Virtualization and ExpandStateMapping we need to maintain the Expand/collapse state in case of TreeGrid re-render. 

If we misinterpreted your query, please elaborate your issue you have faced to proceed further . 

Regards, 
Farveen sulthana T 


Marked as answer
Loader.
Up arrow icon