简体   繁体   中英

Blazor : Pass Component to RenderFragment

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!

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" };
   
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM