Exercise - Data binding and events
In this exercise, you create a basic Todo list component inside your Blazor app.
Create the Todo page
Create the Todo page:
In Visual Studio, right-click the
Components/Pages
folder in Solution Explorer and select Add > Razor Component. Name the componentTodo.razor
.In Visual Studio Code, right-click on the
Pages
folder in Solution Explorer and select Add New File.. > Razor component. Name the componentTodo.razor
. The file should be created inside of thePages
folderImportant
Razor component file names require a capitalized first letter. Expand the
Pages
folder and confirm that theTodo
component file name starts with a capital letterT
. The file name should beTodo.razor
.Open the
Todo
component and add an@page
Razor directive to the top of the file with a relative URL of/todo
.@page "/todo" <h3>Todo</h3> @code { }
Save the
Components/Pages/Todo.razor
file
Add the Todo component to the navigation bar
The app's layout uses the NavMenu
component. Layouts are components that allow you to avoid duplication of content in an app. The NavLink
component renders an HTML anchor tag that can be styled to provide a cue in the app's UI when the app URL matches the link.
Expand the Components/Layout folder in the Solution Explorer and open the NavMenu.razor file. In the <nav>...</nav>
section of the NavMenu component, add the following new <div>...</div>
and NavLink
component for the Todo
component.
In Components/Layout/NavMenu.razor
:
<!-- .. -->
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<!-- ... -->
<div class="nav-item px-3">
<NavLink class="nav-link" href="todo">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Todo
</NavLink>
</div>
</nav>
</div>
Save the Components/Layout//NavMenu.razor
file. The browser should refresh automatically and now have the Todo entry on the navigation bar:
Create a Todo Item
In the Solution Explorer, right-click on the project, then select Add > New Folder. Name the new folder Data.
In the Solution Explorer, right-click the Data folder, then select Add > Class. Name the new class TodoItem.cs, then select Add. This new class will hold a C# class that represents a todo item.
Replace the code from Line 7 down with the following C# code for the TodoItem
class. Declare the Title
as a nullable string by using ?
. Save the file.
namespace BlazorHybridApp.Data;
public class TodoItem
{
public string? Title { get; set; }
public bool IsDone { get; set; } = false;
}
Bind a list of TodoItems
You're now ready to bind a collection of TodoItem
objects to HTML in Blazor. We'll accomplish this by making the following changes in the Components/Pages/Todo.razor
file:
- Add the using declaration for
TodoItem
with@using BlazorHybridApp.Data
. - Add a field for the todo items in the
@code
block. TheTodo
component uses this field to maintain the state of the todo list. - Add unordered list markup and a
foreach
loop to render each todo item as a list item (<li>
).
@page "/todo"
@using BlazorHybridApp.Data
<h3>Todo</h3>
<ul class="list-unstyled">
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
@code {
private List<TodoItem> todos = new();
}
Add form elements to create todos
The app requires UI elements for adding todo items to the list. Add a text input (
<input>
) and a button (<button>
) below the unordered list (<ul>...</ul>
):@page "/todo" @using BlazorHybridApp.Data <h3>Todo</h3> <ul class="list-unstyled"> @foreach (var todo in todos) { <li>@todo.Title</li> } </ul> <input placeholder="Something todo" /> <button>Add todo</button> @code { private List<TodoItem> todos = new(); }
When the
Add todo
button is selected, nothing happens because an event handler isn't attached to the button.Add an
AddTodo
method to theTodo
component and register the method for the button using the@onclick
attribute. TheAddTodo
C# method is called when the button is selected:<input placeholder="Something todo" /> <button @onclick="AddTodo">Add todo</button> @code { private List<TodoItem> todos = new(); private void AddTodo() { // Todo: Add the todo } }
To get the title of the new todo item, add a
newTodo
string field at the top of the@code
block:@code { private List<TodoItem> todos = new(); private string? newTodo; // Omitted for brevity... }
Modify the
<input>
element to bindnewTodo
with the@bind
attribute:<input placeholder="Something todo" @bind="newTodo" />
Update the
AddTodo
method to add theTodoItem
with the specified title to the list. Clear the value of the text input by settingnewTodo
to an empty string:@page "/todo" @using BlazorHybridApp.Data <h3>Todo</h3> <ul class="list-unstyled"> @foreach (var todo in todos) { <li>@todo.Title</li> } </ul> <input placeholder="Something todo" @bind="newTodo" /> <button @onclick="AddTodo">Add todo</button> @code { private List<TodoItem> todos = new(); private string? newTodo; private void AddTodo() { if (!string.IsNullOrWhiteSpace(newTodo)) { todos.Add(new TodoItem { Title = newTodo }); newTodo = string.Empty; } } }
Save the
Components/Pages/Todo.razor
file. Rebuild and restart the app.You can make the title text for each todo editable, and a checkbox can help the user keep track of completed items. Add a checkbox input for each todo item and bind its value to the
IsDone
property. Change the@todo.Title
to an<input>
element bound totodo.Title
with@bind
:<ul class="list-unstyled"> @foreach (var todo in todos) { <li> <input type="checkbox" @bind="todo.IsDone" /> <input @bind="todo.Title" /> </li> } </ul>
Update the
<h3>
header to show a count of the number of todo items that aren't complete (IsDone
isfalse
).<h3>Todo (@todos.Count(todo => !todo.IsDone))</h3>
Save the
Components/Pages/Todo.razor
file and run the app again.Add items, edit items, and mark items done to test the component.