Search code examples
c#blazorblazor-server-sidemudblazor

What is the best approach to have dynamic tabs with dynamic content in Blazor?


Working on a Blazor application, I am wondering what would be the best approach to implement dynamic tabs with dynamic content. I have searched extensively but did not arrive to a satifying conclusion and now am looking for some advice. I hope it is OK to post this here, if not, I'll happily remove the question.

My use case in a nutshell:

  • The app is used to visualize logging data from remote systems (timeseries based data, stored in a database)
  • The user must be able open and close various tabs for each connected system; eg. to visualize raw data of type 1, visualize raw data of type 2, visualize processed data, etc. So, tabs can have a variety of different Components in them, based on what the user chose to access.
  • It should be possible to open the same type of tab multiple times, both for different systems as well as for the same system, ie. to have diferent dates 'open' for a single system.
  • Switching between tabs should be possible without loosing state (or at least it should appear like this)

Currently, I have a frontend app written in WPF. It uses AvalonDock for the above requirements. I am aware I cannot (and probably should not want to) replicate AvalonDock in Blazor, but am hoping to at least be able to have a flexible "tabbed" approach. This looks liek this, to get an idea of the current goal:

dynamic tabs with dynamic content

So far I see two possible approaches:

  1. Have a list of states for open tabs, that are used to serve content via a single Component. I could use OnParametersSet to set the tab id and apply the state, ie. using DynamicComponent or some kind of branching logic. This would kind of mimmick DataTemplate from WPF to choose the right way to display the data. It seems kind of complex to store the complete needed state by hand, but maybe it is the way to go?
  2. Somehow instantiate and store Components as is proposed here. Though I have doubts if that would really allow me to have a disctinct and persistent state per instantiated Component. This would seem like an easier approach, since the state is simply stored with the Component.

Does anyone have some advice here? I am rather new to Blazor and kind of stuck as to how to apporach this problem. Especially the combination of a dynamic number of tabs, with varying/dynamic content based on what the user chooses, seems to be hard to find the best approach for.

Any help appreciated!


Solution

  • Option 2 is NO, so it's option 1.

    You want to display a list of tabs with state. So think Dictionary<Type, Object> where Type is the type of the top level component and Object is the state object for each specific Type. You'll need to cast it in the specific component.

    For example if you are displaying a list it would contain a ListState instance with the current page, the filter and the sort order.

    You need to decide how you persist the dictionary. In a Scoped service if only for the SPA scope, or in protected browser storage if you want to persist across SPA sessions.

    Once you have the list you can build the tabs containing a DynamicComponent based on the dictionary entry. The Type defines the component type to create and the Object, the state data to pass as a parameter.