How to Create a Blazor Component

Blazor components are a great way to write reusable code and follow the DRY principle. There are a few guidelines that are worth following when creating them and a couple ways to create them as well. We're going to start with the default project and turn the button on the Counter page into a component.

Create the project

In your terminal use this command to create a new Blazor WebAssembly project named BlazorApp: ~$ dotnet new blazorwasm -o BlazorApp

Navigate into the project and open it in your IDE of choice: ~$ cd BlazorApp

Create the component

I find it to be easier to keep things organized if we create a folder for our components. Let's create a folder named 'Components' and create our new component file named 'Button' in there.

The name of the file will be the case-sensitive name of the component. It's important to give your components unique names and the common convention in Blazor is to use Pascal Casing.

Another quick thing we're going to do before we continue is add the Components folder to _Imports.razor so it's easily accessible everywhere:

@using BlazorApp.Components

This eliminates the need for you to have a using statement in every file that uses anything in the Components folder.

Let's add a button and some code to Button.razor:

<button class="btn btn-primary" @onclick="OnClick">
    @Text
</button>

@code {
    [Parameter]
    public string Text { get; set; } = "Click me";

    [Parameter]
    public EventCallback OnClick { get; set; }
}

This is a pretty simple component. We have two parameters:

  • Text is a string with a default value of "Click me".

  • OnClick is how we add a handler to the click event

Use the component

Now we can replace the button in Counter.razor with our new Button component and see it in action!

<Button Text="My Button Text" OnClick="IncrementCount" />

That's it! Run the app, go to the Counter page and click away to watch the count go up.

Let's try something a bit more complicated.

Data Binding

Let's make a text input component that we can bind to. Data binding allows us to write code that will automatically update properties or allow us to handle when a value has changed. Let's create a new file for the new component TextInput.razor:

And add some code:

<input type="text" value="@Text"
    @oninput="e => TextChanged.InvokeAsync(e.Value?.ToString())" />

@code {
    [Parameter]
    public string Text { get; set; } = string.Empty;
    [Parameter]
    public EventCallback<string> TextChanged { get; set; }
}

This new TextInput component allows us to bind to the Text property through a convention. You'll notice the TextChanged property above. It has the same name as the property we are binding to with Changed appended to it and the type in the angle brackets of EventCallback matches the type of the property. Then all we need to do is InvokeAsync() and the property is set up for binding!

Let's add this component to the Index page:

<TextInput @bind-Text="Text" />

<div>Your text: @Text</div>

@code {
    private string Text { get; set; } = string.Empty;
}

Now we have a text input on the Index page and when we type in it the page updates to show the text just below it:

Required Parameters

If you design a component that requires a parameter for it to render properly there is a way to make it show a warning in your IDE when it hasn't been passed in. It's as simple as adding EditorRequired to the Parameter attribute:

// Button.razor
<button class="btn btn-primary" @onclick="OnClick">
    @Text
</button>

@code {
    [Parameter, EditorRequired]
    public string Text { get; set; } = "Click me";

    [Parameter]
    public EventCallback OnClick { get; set; }
}

Now when you add a Button to a page it will have a yellow squiggle underneath it in your IDE if the Text parameter has not been set!

I hope you found this helpful! Happy coding!

Did you find this article valuable?

Support Ryan Phillips by becoming a sponsor. Any amount is appreciated!