Arad
Arad

Reputation: 12734

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.

Upvotes: 14

Views: 17195

Answers (1)

Brian Parker
Brian Parker

Reputation: 14553

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; }
}

Upvotes: 32

Related Questions