Blazor provides fantastic helper components to make creating HTML forms simple so your web app can accept user data.
Modern web applications aren’t one-way streets. Users interact with our applications by navigating the website or web application or, most importantly, entering data.
In this part of the Blazor Basics series, we will learn how to create HTML forms to capture user data.
As a short teaser, Blazor offers a set of fantastic helper components to deal with form creation and form handling.
You can access the code used in this example on GitHub.
In this post, we will create a simple login form accepting the user’s username and password. We also want to use a masked password field. This example will demonstrate how you can build simple forms using Blazor.
First of all, we need a form. Blazor provides components wrapping the HTML form element to make creating forms more developer-friendly.
<EditForm Model="@UserData" OnSubmit="@Submit">
</EditForm>
The built-in EditForm
component wraps the HTML form
element.
It provides an OnSubmit
property where we can provide a method that is called when the form is submitted.
There are two main approaches to implementing forms when using the EditForm
component. We can provide a Model
property as shown above, or we can create and provide an EditContext
. The EditContext
allows for more granular control.
However, we do not need that for our basic example. Instead, we prefer providing a Model
property. It will create an EditContext
behind the scenes.
Next, we add a submit button
to the component template inside the EditForm
component instance.
<EditForm Model="@UserData" OnSubmit="@Submit">
<button class="btn btn-primary" type="submit">Log in</button>
</EditForm>
We use a default HTML button
element and provide a few Bootstrap classes to style it. We also set the type
to submit
.
Blazor comes with built-in input components. Those components follow a naming convention and always start with “Input”. The following components are available:
All input components wrap the native HTML input control and provide helpful properties and events.
Besides the provided events and properties, we can add regular HTML attributes when input controls are used.
For example, we can use the InputText
control and set the HTML type
attribute to password
to mask the user input.
The built-in input controls use the EditContext
provided by the EditForm
component to access the model properties. More specifically, it uses cascading parameters behind the scenes.
For our example, we add two InputText
components to define an input field for the username and for the password.
<InputText @bind-Value="UserData.Username" />
<InputText type="password" @bind-Value="UserData.Password" />
As stated above, the built-in input types access the model provided to the EditForm
component using the EditContext
. It allows us to bind the Value
property of the InputText
component to a property of the UserData
variable.
It’s important that we use the name of the variable provided to the Model
property of the EditForm
component. Otherwise, you will get a compiler error stating that the variable is not known in this context.
Notice that we set the HTML type
attribute to the second InputText
instance. The form field will mask the input when the user enters their password. It’s a regular HTML attribute.
The whole component, including a few div
s to make it more appealing, looks like this:
<h1>Login</h1>
<EditForm Model="@UserData" OnSubmit="@Submit">
<div style="margin-bottom: 10px;">
<div>Username</div>
<InputText @bind-Value="UserData.Username" />
</div>
<div style="margin-bottom: 10px;">
<div>Password</div>
<InputText type="password" @bind-Value="UserData.Password" />
</div>
<button class="btn btn-primary" type="submit">Log in</button>
</EditForm>
With only about 15 lines of code, we create a form with two input fields, a submit button and labels. We also provide a UserData
object as the Model
property and add a click handler to the OnSubmit
property of the EditForm
component.
We already provided the Submit
method as the OnSubmit
event handler for the EditForm
component. Now, let’s implement the Submit
method within the @code
section of our form component.
@code {
public User UserData { get; set; }
public string FormCompletedText { get; set; } = "";
protected override void OnInitialized()
{
UserData = new User();
}
public void Submit()
{
FormCompletedText = $"User {UserData.Username} logged in.";
}
public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
}
We create two string
properties. The UserData
property holds the form data provided by the user. The FormCompletedText
will be populated with a text we want to show when the user has logged in.
The Submit
method is executed when a user submits the form by pressing the submit button. Within the method, we access the UserData
property that contains the values the user has put into each input field.
We access the Username
property and write a short message for the user to confirm the login was successful.
We add the following template snippet to the template section of the component to display the message to the user.
<p style="margin-top: 20px;">@FormCompletedText</p>
It will show the text set in the Submit
method to the user whenever they press the login button.
Similar to regular HTML forms, we can use a button
of type
“reset” to reset the values in input fields.
We add the following line below the existing submit button within the EditForm
component instance.
<button class="btn btn-secondary" type="reset">Reset</button>
When the user presses the button, the form fields are cleared.
Note: Keep in mind that this only clears the input fields visible on the screen. If we also want to reset the values within the UserData
object, we need to add a Reset
method and add it as an event handler to the onReset
property of the EditForm
component.
However, resetting form fields using a reset button isn’t as common as it once was. More commonly, you want to reset the fields when a form has been submitted.
The implementation is simple. We add the following line to the Submit
method.
public void Submit()
{
FormCompletedText = $"User {UserData.Username} logged in.";
UserData = new User();
}
The second line of the Submit
method creates a new instance of the User
class and assigns it to the UserData
property.
Form fields use a two-way binding, meaning that values changed in the code will also be reflected on the screen. As a result, all form fields are empty after submitting the form.
The code above doesn’t account for nullable reference types (NRTs).
If you coded along, you definitely saw at least three compiler warnings caused by nullable reference types.
Let’s fix those warnings.
First, we add a default non-null value to the properties of the User
class.
public class User
{
public string Username { get; set; } = "";
public string Password { get; set; } = "";
}
In this case, we set an empty string to both properties.
Next, instead of assigning an instance of the User
class to the UserData
property in the OnInitialized
lifecycle method, we initialize the value when declaring the property.
@code {
public User UserData { get; set; } = new User();
public string FormCompletedText { get; set; } = "";
public void Submit()
{
FormCompletedText = $"User {UserData.Username} logged in.";
UserData = new User();
}
public class User
{
public string Username { get; set; } = "";
public string Password { get; set; } = "";
}
}
This version is not only shorter, doesn’t need an explicit OnInitialized
override, but also fixes all nullable reference type-specific compiler warnings.
Blazor allows us to implement HTML forms using wrapper components. Those components provide a great API for event handling. We can add methods to handle form submits or form resets conveniently.
The built-in input wrapper components, such as the InputText component, allow us to add standard HTML attributes, such as type. And we can use the powerful two-way binding mechanism provided by the Blazor component model.
With less than 40 lines of code, we have a fully working HTML form, including a type-safe data class and form handling code. Of course, you would probably add more logic to the Submit method in a real-world application, such as calling a backend to verify the user data.
In the next article, we learn about different form validation options. Read it here: Blazor Basics: Advanced Blazor Form Validation.
You can access the code used in this example on GitHub.
If you want to learn more about Blazor development, you can watch my free Blazor Crash Course on YouTube. And stay tuned to the Telerik blog for more Blazor Basics.
Looking for something even easier? Among 110+ native Blazor components, Progress Telerik UI for Blazor offers a versatile Form component, complete with built-in validation. Try the whole library free for 30 days.
Claudio Bernasconi is a passionate software engineer and content creator writing articles and running a .NET developer YouTube channel. He has more than 10 years of experience as a .NET developer and loves sharing his knowledge about Blazor and other .NET topics with the community.