Search code examples
inheritancerazorblazor

Blazor - Base Render in an inherited component doesn't use overridden methods


I'm trying to make a Blazor component that I will then specialize and override some methods.

Base Component "ZoomList":

@inherits ComponentBase
<div>
    <table class="table">
        <thead>
            <tr>
                @foreach (var str in Headers())
                {
                    <th>@str</th>
                }
            </tr>
        </thead>
        <tbody>
            @foreach (var item in items)
            {
                <tr>
                    @foreach (var str in Rows(item))
                    {
                        <td>@str</td>
                    }
                </tr>
            }
        </tbody>
    </table>
</div>

@code {
    [Parameter]
    public List<Object> items { get; set; }

    protected virtual List<string> Rows(Object item) { return new List<string>() { "Placeholder" }; }
    protected virtual List<string> Headers() { return new List<string>() { "Placeholder" }; }
}

Derivated component "ZoomCampaign":

@inherits ZoomList
@using MyNamespace.Model

@{
    this.BuildRenderTree(__builder);
}

@code {

    protected override List<string> Rows(Object item)
    {
        Campaign camp = item as Campaign;
        return new List<string>() {
            camp.Id.ToString(),
            camp.Nom
        };
    }

    protected override List<string> Headers()
    {
        return new List<string>() { "#", "Name" };
    }
}

ZoomCampaign is then called from another page. But this.BuildRenderTree(__builder) doesn't use the overridden methods but is using the base methods. => My html array is contains the "Placeholder" text, not the text defined in override methods "Rows" and "Headers" from ZoomCampaign.

What am I missing ? How can I change it so that override methods are the ones that are used during rendering ?


Solution

  • As mentioned in another answer, this is not how components work - specifically this code should be removed from ZoomCampaign:

    @{
        this.BuildRenderTree(__builder);
    }
    

    You can look at the generated code (ZoomCapaign.razor.g.cs) to see what is going wrong.

    When you put that code in the markup of a razor component, you are basically saying "hey, when you come to render ZoomCampaign, please render ZoomCapaign"

    This is worse than redundant (ZoomCapaign is already being rendered) as it has introduced a bug.

    Solution

    Remove the code mentioned above. Additionally, your ZoomCapaign component does not use any Razor features and can be implemented in a simpler, cleaner, (less prone to this kind of error) way as a csharp file ZoomCampaign.cs instead.

    Try it here : https://blazorrepl.com/repl/QvkQuMOX35G4Syyg08 _I did not override Rows in this sample because I don't have the model, but you can see the Headers override is working.