'In Blazor, how can I dynamically change an HTML tag?

Let's say I have the following markup in my Blazor component:

<div @attributes=Attributes data-myattr="something">
    @ChildContent
</div>

I'd like to provide a way for the parent component to determine which tag is going to be used in place of <div>. Something like:

<@Tag @attributes=Attributes data-myattr="something">
    @ChildContent
</@Tag>

With @Tag being a string Parameter. Of course that doesn't work. I'm aware of templates but it doesn't work for me because I want to be in control the structure of the tag, and add extra attributes to it. I just want to give the user a choice of which tag is going to be displayed.



Solution 1:[1]

Instead of having a .razor file create a .cs file.

In the file create your class public class MyComponent: ComponentBase

and then override BuildRenderTree

NOTE: You'll need to add ? after the Dictionary<string, object and RenderFragment in later versions to indicate they are nullable.

protected override void BuildRenderTree(RenderTreeBuilder builder)
{
  builder.OpenElement(0, YourParameter);
  builder.CloseElement();
}

If you don't know exactly how to use the RenderTreeBuilder, simply create a temporary razor file and create the markup you want, then look in obj\Debug\netstandard2.1\Razor\

If you want to achieve this in a .razor file then you can create a component like this following

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;

namespace BlazorApp118.Shared
{
    public class Dynamic : ComponentBase
    {
        [Parameter]
        public string Tag { get; set; }

        [Parameter]
        public Dictionary<string, object> AdditionalAttributes { get; set; }

        [Parameter]
        public RenderFragment ChildContent { get; set; }

        protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            if (string.IsNullOrWhiteSpace(Tag))
                throw new ArgumentNullException(nameof(Tag));

            builder.OpenElement(0, Tag);
            if (AdditionalAttributes?.Any() == true)
                builder.AddMultipleAttributes(1, AdditionalAttributes);
            if (ChildContent != null)
                builder.AddContent(2, ChildContent);
            builder.CloseElement();
        }
    }
}

And then use it like this

<Dynamic Tag="a" AdditionalAttributes=@SomeDictionaryOfValues>
  Any content you want here
</Dynamic>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1