blazor-input-components-text-number-select

Blazor Input Components: text, numbers and selection

  • 5 min

The Input components are Blazor controls that bind a value and notify their changes to the form’s editing context.

Why? Because a standard <input @bind="Age"> updates the variable, but does not communicate with the EditContext. If the user enters invalid text, the EditForm has no easy way to mark that specific field as “invalid” and apply error CSS classes to it.

Inside an EditForm, we will typically use the controls that inherit from InputBase<T>.

These components do three things:

Binding: They synchronize the value with @bind-Value.

Parsing: They convert the HTML string to the C# data type (int, decimal, DateTime, Enum).

Validation: They subscribe to the EditContext to know whether they are valid or not, and automatically change their CSS class.

Let’s meet the key players.

InputText and InputTextArea

These are the most basic ones. They are used for string type properties.

  • InputText: Renders an <input type="text">.
  • InputTextArea: Renders a <textarea>.
<div class="mb-3">
    <label>Article Title</label>
    <InputText class="form-control" @bind-Value="Article.Title" />
</div>

<div class="mb-3">
    <label>Content</label>
    <InputTextArea class="form-control" @bind-Value="Article.Content" rows="5" />
</div>
Copied!

Notice we use @bind-Value (with capital V) instead of @bind. This is the convention for Blazor components that expose an explicit Value property.

InputNumber

This component is important for numeric data (int, double, decimal, float). It renders an <input type="number">.

The great advantage is that if the user types something that is not a number, Blazor handles the conversion error internally and marks the field as invalid, instead of throwing an exception that would break the application.

<label>Price (€)</label>
<InputNumber class="form-control" @bind-Value="Product.Price" />
Copied!

InputDate

Renders a date or time <input>. It supports types like DateTime, DateTimeOffset, DateOnly and TimeOnly, also in their nullable variants where applicable. It automatically handles the browser’s local format (yyyy-MM-dd), so we don’t have to wrestle with date formats.

<label>Release Date</label>
<InputDate class="form-control" @bind-Value="Product.ReleaseDate" />
Copied!

With the Type parameter you can choose values like InputDateType.DateTimeLocal, InputDateType.Date, InputDateType.Month or InputDateType.Time.

InputCheckbox

Renders an <input type="checkbox"> and binds to bool properties.

<div class="form-check">
    <InputCheckbox class="form-check-input" @bind-Value="Product.IsActive" />
    <label class="form-check-label">Product Available</label>
</div>
Copied!

InputSelect for dropdown lists

In plain HTML, a <select> always returns a string. If your model expects an int (category ID) or an Enum (Product Type), in JavaScript you would have to convert it manually.

InputSelect handles the type conversion automatically.

Example with integers

<label>Category</label>
<InputSelect class="form-select" @bind-Value="Product.CategoryId">
    <option value="">-- Select --</option>
    @foreach (var cat in Categories)
    {
        <option value="@cat.Id">@cat.Name</option>
    }
</InputSelect>

@code {
    // If Product.CategoryId is int, Blazor will convert the option's "value" to int.
}
Copied!

Example with enumerations

This is quite convenient. Blazor knows how to iterate and parse Enums.

public enum Colors { Red, Green, Blue }
// In the model: public Colors FavoriteColor { get; set; }
Copied!
<label>Color</label>
<InputSelect class="form-select" @bind-Value="Model.FavoriteColor">
    @foreach (var color in Enum.GetValues<Colors>())
    {
        <option value="@color">@color</option>
    }
</InputSelect>
Copied!

InputRadioGroup for radio buttons

Radio buttons work in groups. Blazor manages this with a container component InputRadioGroup and child components InputRadio.

<label>Urgency Level:</label>

<InputRadioGroup @bind-Value="Ticket.Urgency">

    <div class="form-check">
        <InputRadio Value="1" class="form-check-input" />
        <label>Low</label>
    </div>

    <div class="form-check">
        <InputRadio Value="2" class="form-check-input" />
        <label>Medium</label>
    </div>

    <div class="form-check">
        <InputRadio Value="3" class="form-check-input" />
        <label>High</label>
    </div>

</InputRadioGroup>
Copied!

The cool thing is that the Value can be of any type (int, string, enum), and the RadioGroup will take care of selecting the correct one.

Automatic CSS classes

One of the best features of using these components is that Blazor automatically adds and removes CSS classes based on the field’s state.

Depending on the field’s state, the EditContext’s class provider uses modified, valid and invalid. For example, an edited field with errors might end up as class="form-control modified invalid".

This allows us to give instant visual feedback with just CSS, without touching C#.

/* app.css */

/* Green border if modified and valid */
.modified.valid {
    border: 2px solid green;
}

/* Red border if invalid (modified or not) */
.invalid {
    border: 2px solid red;
    background-color: #ffe6e6;
}
Copied!

Integrated example

Let’s put it all together in an employee registration form.

<EditForm Model="@Employee" OnValidSubmit="Save">
    <DataAnnotationsValidator />

    <div class="row g-3">
        <div class="col-md-6">
            <label>Name</label>
            <InputText @bind-Value="Employee.Name" class="form-control" />
        </div>

        <div class="col-md-6">
            <label>Age</label>
            <InputNumber @bind-Value="Employee.Age" class="form-control" />
        </div>

        <div class="col-12">
            <label>Department</label>
            <InputSelect @bind-Value="Employee.Department" class="form-select">
                <option value="IT">Technology</option>
                <option value="HR">Human Resources</option>
                <option value="MK">Marketing</option>
            </InputSelect>
        </div>

        <div class="col-12">
            <div class="form-check">
                <InputCheckbox @bind-Value="Employee.IsManager" class="form-check-input" />
                <label class="form-check-label">Is Team Manager</label>
            </div>
        </div>
    </div>

    <button type="submit" class="btn btn-primary mt-3">Save Employee</button>
</EditForm>

@code {
    public class EmployeeModel
    {
        public string Name { get; set; } = string.Empty;
        public int Age { get; set; }
        public string Department { get; set; } = "IT";
        public bool IsManager { get; set; }
    }

    private EmployeeModel Employee = new();

    private void Save() { /* ... */ }
}
Copied!