Search code examples
c#asp.net-coreblazorblazor-webassemblyrazorengine

How to use either ?. or ?? to conditionally render Blazor template?


I want to simplify the following

@if (Template != null)
{
    @Template
}
else
{
    <span>No contents!</span>
}

with either ?? or ?.

Is it possible?

Attempt

My attempts below

  • @Template?.BeginInvoke()
  • @{Template==null? @Template : <span> No data to display! </span>}
  • @(Template??<span> No data to display! </span>)

produce red squiggly lines.

Edit

I think I need to submit the real scenario that I want to simplify.

@typeparam T

@if (Items == null)
{
    if (NullTemplate != null)
    {
        @NullTemplate
    }
    else
    {
        <span style="color: red">Null...</span>
    }
}
else if (Items.Count == 0)
{
    if (EmptyTemplate != null)
    {
        @EmptyTemplate
    }
    else
    {
        <span style="color: red">Empty ...</span>
    }
}
else
{
    @HeaderTemplate

    foreach (T item in Items)
    {

        @ItemTemplate(item)
    }
}

    
@code{
    [Parameter] public RenderFragment NullTemplate { get; set; }
    [Parameter] public RenderFragment EmptyTemplate { get; set; }
    [Parameter] public RenderFragment HeaderTemplate { get; set; }
    [Parameter] public RenderFragment<T> ItemTemplate { get; set; }
    [Parameter] public List<T> Items { get; set; }
}

I don't want to buffer the incoming values to ****Template properties with private fields, pre-process the fields before rendering them (the fields) to HTML. In other words, no additional code in @code{} directive are allowed.


Solution

  • It could work (I think) when you store the <span style="color: red">Null...</span> parts as RenderFragments. Would that be acceptable?

    That would move this logic to the constructor or the SetParameters method.

    [Parameter] public RenderFragment NullTemplate { get; set; } = builder => StubTemplate(builder, "Null");
    [Parameter] public RenderFragment EmptyTemplate { get; set; } = builder => StubTemplate(builder, "Empty");
    
    private static void StubTemplate(RenderTreeBuilder __builder, string what)
    {
        <span style="color: red">@what</span>
    }
    

    Note that the __builder name is required.
    And then you don't need any conditional code in the main component anymore:

    @if (Items == null)
    {
       @NullTemplate
    }
    

    Alternatively, you can omit the property initialization and do :

     @(EmptyTemplate ?? (builder => StubTemplate(builder, "Empty")))
    

    but I would get dizzy of all the ().