Search code examples
renderingblazor-server-sidemudblazor

Identify which MudExpansionPanel is being expanded


I want to present a list of up to 20 panels within a <MudExpansionPanels> component where the expanded child portion of each <MudExpansionPanel> is expensive to render. I tried the following test code but all instances of <LiveAgentSummary> are rendered as the parent is rendered, just to clarify this rendering of <LiveAgentSummary> happens before any panel is manually expanded.

<MudExpansionPanels>
    @foreach (var liveAgent in _liveAgents)
    {
        <MudExpansionPanel [email protected]>
            <LiveAgentSummary [email protected] />
        </MudExpansionPanel>
    }
</MudExpansionPanels>

I then looked into delaying the render of each <LiveAgentSummary> through use of a RenderFragment that is dynamically built during the <MudExpansionPanel> IsExpandedChanged event. However the event handler does not indicate which panel is being expanded and hence I do not know which liveAgent.Id param value to pass to <LiveAgentSummary> as I build a RenderFragment.

I think <MudExpansionPanels> is missing support for a bind-ActivePanelId property but hopefully I am overlooking an alternative solution to my delayed rendering objective.

This is the official MudBlazor example that prompted me to look into using a RenderFragment.

Update: A long answer briefly appeared yesterday suggesting that I could query the list of panel components on a built-in property that indicates the expanded state. The poster had gone to the trouble of reading the MudBlazor source code but the answer was then deleted.

I am now wondering how from code in an event handler it is possible to iterate over a component hierarchy declared as mark-up. Applying this to my example markup above, how could event handler code obtain a reference to each <MudExpansionPanel> child within <MudExpansionPanels>.


Solution

  • Can't you make use of the bool from the IsExpandedChanged callback? Something like this:

    Index.razor

    @page "/"
    
    <MudExpansionPanels>
      @foreach (var liveAgent in this.liveAgents)
      {
        <MudExpansionPanel
          Text="@($"{liveAgent.Name} ({liveAgent.Data})")"
          IsExpandedChanged="@(e => this.Load(e, liveAgent))">
    
          <LiveAgentSummary Agent="@liveAgent" />
        </MudExpansionPanel>
      }
    </MudExpansionPanels>
    
    @code {
      private readonly List<Agent> liveAgents = new()
      {
        new Agent("1", "Agent Smith"),
        new Agent("2", "Agent Brown"),
        new Agent("3", "Agent Jones")
      };
    
      private void Load(bool expanded, Agent agent)
      {
        if (expanded)
        {
          agent.Load();
        }
      }
    }
    

    LiveAgentSummary.razor

    <MudText>id: @this.Agent.Id, data: @this.Agent.Data</MudText>
    
    @code {
      [Parameter]
      public Agent Agent { get; set; } = default!;
    }
    

    Agent.cs

    public record Agent(string Id, string Name)
    {
      public string Data { get; set; } = "Not loaded";
    
      public void Load()
      {
        Console.WriteLine($"Loading agent {this.Id}...");
    
        this.Data = "Loaded!";
      }
    }