Search code examples
c#asp.net.netblazorradix

How to create `AsChild` or `Slot` within Blazor


I have been searching for an answer to this question for a long time. All I want is to be able to recreate the Radix's slot component/asChild pattern within Blazor.

e.g.

<Button AsChild>
    <a href="/contact">Contact</a>
</Button>

Solution

  • Thanks to @DanielD for putting me on the right track.

    I created an abstract class (you don't need to do this, you can just add these properties to whichever component you would like to have this functionality).

    public abstract class Slot : ComponentBase
    {
        [Parameter]
        public required RenderFragment<Dictionary<string, object>> ChildContent { get; set; }
    
        [Parameter]
        public bool AsChild { get; set; }
    }
    

    Button.razor.cs

    Specify the attributes that you would like to get splatted.

    public partial class Button : Slot
    {
        private static Dictionary<string, object> _attributes =>
            new() { { "onclick", () => Console.WriteLine("Button was clicked!") } };
    }
    

    Button.razor

    Create the markup for your default component (when AsChild is not being used).

    @inherits Slot
    
    @if (AsChild)
    {
        @ChildContent(_attributes)
    }
    else
    {
        <button type="button" @attributes="_attributes">
            @ChildContent(_attributes)
        </button>
    }
    

    Now you can use the following wherever you like.

    Usage of AsChild:

    <Button AsChild>
        <a href="#" @attributes="context">Click me!</a>
    </Button>
    

    Usage without AsChild:

    <Button>
        Click me!
    </Button>