Search code examples
genericsinheritanceblazorrendering

Struggling around with RenderFragement<T> returning a Detail Template for a razor base component


I try to implement a generic razor base component, but cannot find out the correct syntax when passing the context to the child. This is my base class

@typeparam T where T : class
....
<GridColumns>
  @Columns
</GridColumns
....
<DetailTemplate>
   @Deatil((T) context)
</DetailTemplate>

@code {
  protected override RenderFragment Columns { get; }
  protected override RenderFragment<T> Detail { get; } 

And in my derived child I try to define those templates,

 protected override RenderFragment Columns
{
    get
    {
        return __builder =>
        {
            <GridColumn Field="Id" Title="#" />
            <GridColumn Field="Name" />
            .....
        };
    }
}

This is working, however I can't find out how to provide the template for the detail

protected override RenderFragment<T> Detail => currentT => __builder =>
{
    get             // <== compiler claims a missing ; here
    {
        return __builder =>
        {
            if (currentT.ParentId == null)
            {
                <h1>One</h1>
            }
            else
            {
                <h1>Two</h1>
            }
        };
    };
};

Can anyone point me in the right direction?


Solution

  • You don't need to use get, the third => defines the getter implicitly. There is also no return value. RenderFragment is a delegate defined as follows:

    public delegate void RenderFragment(RenderTreeBuilder builder);
    

    As there's not enough detail to use your code, here's an example of how to build and consume a RenderFragment<T> using Razor markup.

    @page "/fetchdata"
    @using Blazr.Data
    @inject WeatherForecastService ForecastService
    
    <PageTitle>Weather forecast</PageTitle>
    
    <h1>Weather forecast</h1>
    
    <p>This component demonstrates fetching data from a service.</p>
    
    @if (forecasts == null)
    {
        <p><em>Loading...</em></p>
    }
    else
    {
        <table class="table">
            <thead>
                <tr>
                    <th>Date</th>
                    <th>Temp. (C)</th>
                    <th>Temp. (F)</th>
                    <th>Summary</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var forecast in forecasts)
                {
                    @Detail(forecast)
                }
            </tbody>
        </table>
    }
    
    @code {
        private WeatherForecast[]? forecasts;
    
        protected override async Task OnInitializedAsync()
        {
            forecasts = await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
        }
    
        protected RenderFragment<WeatherForecast> Detail
            => context => __builder =>
                {
                    <tr>
                        <td>@context.Date.ToShortDateString()</td>
                        <td>@context.TemperatureC</td>
                        <td>@context.TemperatureF</td>
                        <td>@context.Summary</td>
                    </tr>
                };
    }