I am trying to pass a ListItem component to a List component to be displayed.
The ListItem Component looks like this: Razor:
<li>
@Item
</li>
C#
using Microsoft.AspNetCore.Components;
namespace Components
{
public partial class TextListItem
{
[Parameter]
public new string Item { get; set; }
}
}
This should just show a list item with text in it.
The List Component looks like this: Razor:
@typeparam T
<ul>
@foreach(T item in Items)
{
@ChildContent(item)
}
</ul>
using Microsoft.AspNetCore.Components;
namespace Components
{
public partial class ListComponent<T>
{
[Parameter]
public List<T> Items { get; set; }
[Parameter]
public RenderFragment<T> ChildContent { get; set; }
}
}
This should just fill the unordered list with list items.
And then in Index I have something like:
<ListComponent Items = "@textList" >
@context.Item
</ListComponent>
@code{
private List<TextListItem> textList;
protected override void OnInitialized()
{
base.OnInitialized();
textList = new List<TextListItem>()
{
new TextListItem(){Item ="one" },
new TextListItem(){Item ="two" },
new TextListItem(){Item ="three" },
};
}
}
I don't get back HTML from the list textList, just the text in Item. I am making this complex because I want to get various fragment of HTML back for different types of lists. Why don't I get the HTML back? I think I am supposed to. Thanks!
CodePudding user response:
What you actually want to do is to create a templated component, which renders the use of the TextListItem superfluous, which is, in any case is not only not used in your code, but is not possible.
This: new TextListItem(){Item ="one" }
is not allowed in Blazor. You can't create a Razor component like that... Item is a component parameter, and you can't set it like that. Didn't you get a warning message telling you not to modify the component's state outside of the component.
Here's the code how to do that. Copy and test.
ListComponent.razor.cs
public partial class ListComponent<TValue>
{
[Parameter]
public List<TValue> Items { get; set; }
[Parameter]
public RenderFragment<TValue> ChildContent { get; set; }
}
ListComponent.razor
@typeparam TValue
<ul>
@foreach (TValue item in Items)
{
@ChildContent(item)
}
</ul>
@code {
}
Index.razor
@page "/"
<ListComponent Items="@textList" Context="Item">
<li>@Item</li>
</ListComponent>
@code{
private List<string> textList = new List<string> { "one", "two", "three" };
}
CodePudding user response:
I was able to make your example work by using DynamicComponent
: https://learn.microsoft.com/en-us/aspnet/core/blazor/components/dynamiccomponent?view=aspnetcore-6.0
<ListComponent Items="@textList">
<DynamicComponent Type="@context.GetType()"
Parameters="@(new Dictionary<string, object> { { nameof(context.Item), context.Item } })" />
</ListComponent>
@code {
private List<TextListItem> textList;
protected override void OnInitialized()
{
base.OnInitialized();
textList = new List<TextListItem>()
{
new TextListItem() { Item = "one" },
new TextListItem() { Item = "two" },
new TextListItem() { Item = "three" },
};
}
}
I have never used this in my projects and it is probably a terrible idea so experiment with it and use at your own risk.