Search code examples
blazorblazor-server-sideblazor-webassembly

How to add HTML attributes (class, etc.) to Blazor components?


This seems like a very basic question but I have yet to find the answer I'm looking for.

Say you have a Blazor component called <Button>, this component has parameters like Label, etc. These parameters are received like HTML attributes when you use the component:

<Button Label="Sign Up" />

But how do you set actual HTML attributes for the component?! For example, say you want to give additional classes to the element that the component represents, or a title attribute, or role, or type, etc. The following obviously wouldn't work, because all of the attributes on a component tag are expected to be parameters of that component:

<Button Label="Sign Up" class="foo" type="submit" id="bar" />

So, the only way I can think of is declaring a parameter (public property) for each of those attributes inside that component.

<button type="@Type" class="button @Class" id="@Id">@Label</button>

@code {
    [Parameter]
    public string Class { get; set; }

    [Parameter]
    public string Type { get; set; }

    [Parameter]
    public string Role { get; set; }

    [Parameter]
    public string Id { get; set; }

    // And others
}

And then when using the component you do this:

<Button Label="Sign Up" Class="foo" Id="bar" Type="Submit" />

But this obviously doesn't seem ideal. It's not convenient, and it seems like an unnecessary layer of abstraction.

So, my question is: How should this be done? What is the "standard" way to do it, if there is such a thing. Isn't there a more convenient way of doing it than declaring parameters for each attribute?

I'm new to SPA frameworks in general, so I would also like to know how this is usually done in other SPA frameworks as well (e.g. React, Angular, Vue, etc.)

Thanks.


Solution

  • You are after attribute splatting :

    <button @attributes="@InputAttributes">@ChildContent</button>
    
    @code {
        [Parameter(CaptureUnmatchedValues = true)]
        public Dictionary<string, object> InputAttributes { get; set; }
    
        [Parameter]
        public RenderFragment ChildContent { get; set; }
    }