I've been trying to render a list of components dynamically as demonstrated below:
<ul>
@foreach (fruit of fruits)
<li>HOW DO I RENDER FRUIT HERE??? </li> // render the fruit component
</ul>
@code {
// Each member in the list is a subtype of Fruit
var fruits = List<FruitComponent> {
new PearComponent(),
new AppleComponent()'
new BananaComponent(),
new RasberryComponent()
}
So far, I can't find a straight answer officially or unofficially on how to do this. Given the rapid rate of changes, it's difficult to know whether the suggestions I found are even relevant anymore.
The most common method suggested is to use conditional markup to determine the component's type and declare the appropriate tag:
<ul>
@foreach (fruit in fruits)
{
switch(fruit)
{
case PearComponent p:
<PearComponent ParameterOfSomeSort="p"></PearComponent>
<li>Or render pears like this, if you want the li in it</li>
break;
case AppleComponent a:
<AppleComponent></AppleComponent>
break;
case BananaComponent b:
<BananaComponent></BananaComponent>
break;
case RaspberryComponent r:
<RaspberryComponent></RaspberryComponent>
break;
}
}
</ul>
While workable, the code is tightly coupled to the FruitComponent subtypes. Consequently, you can't render a new subtype without code modification. I'll spare you the details of the other approach which emits markup from the code behind. I rather not go back to the old days of ASP.NET Forms Server Control development.
Does Blazor even support this as a first class citizen? It's hard to believe it doesn't as it is a very common use case, especially when DI is baked into dotnetcore. Is there a way to do this, preferably in a declarative way as Vue.js does?
Thanks for contacting us, @Joebeazelman.
Using the switch approach you have will be our recommendation. We will consider doing something better in this area in the future.
This is the solution I came to
@page "/"
@foreach (CounterParent counter in components)
{
RenderFragment renderFragment = (builder) => { builder.OpenComponent(0, counter.GetType()); builder.CloseComponent(); };
<div>
<div>Before the component</div>
@renderFragment
<div>Afterthe component</div>
</div>
}
@code
{
List<CounterParent> components = new List<CounterParent>() { new CounterParent(), new CounterChild() };
}
I posted it in stackoverflow, but I share it here maybe for future reference.
Regards!
Most helpful comment
This is the solution I came to
I posted it in stackoverflow, but I share it here maybe for future reference.
Regards!