Blazor Todo リスト アプリを構築する
注意
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
このチュートリアルでは、Blazor アプリを構築および変更するための基本的な作業エクスペリエンスを提供します。 Blazor の詳細なガイダンスについては、Blazor のリファレンス ドキュメントを参照してください。
具体的には、次の方法を学習します。
- Todo リストの Blazor アプリ プロジェクトを作成する
- Razor コンポーネントを変更する
- コンポーネントでイベント処理とデータ バインディングを使用する
- Blazor アプリでルーティングを使用する
このチュートリアルの最後には、動作する ToDo リスト アプリが完成します。
前提条件
まだシステムにインストールされていない場合、またはシステムに最新バージョンがインストールされていない場合は、.NET をダウンロードしてインストールします。
Blazor アプリを作成する
コマンド シェルで TodoList
という名前の新しい Blazor Web App を作成します。
dotnet new blazor -o TodoList
-o|--output
オプションを指定すると、プロジェクト用のフォルダーが作成されます。 プロジェクト用のフォルダーを作成し、そのフォルダーでコマンド シェルが開いている場合は、-o|--output
オプションと値を省略してプロジェクトを作成します。
次のいずれかのホスティング モデルを使用してコマンド シェルで TodoList
という名前の新しい Blazor アプリを作成します。
Blazor Server を使用したエクスペリエンスでは、次のコマンドを使用してアプリを作成します。
dotnet new blazorserver -o TodoList
Blazor WebAssembly を使用したエクスペリエンスでは、次のコマンドを使用してアプリを作成します。
dotnet new blazorwasm -o TodoList
上記のコマンドでは、アプリを保持するために -o|--output
オプションを指定して、TodoList
という名前のフォルダーを作成します。 TodoList
フォルダーは、プロジェクトのルート フォルダーです。 次のコマンドを使用して、ディレクトリを TodoList
フォルダーに変更します。
cd TodoList
Todo リスト Blazor アプリを構築する
次のコマンドを使用して、新しい Todo
Razor コンポーネントをアプリに追加します。
dotnet new razorcomponent -n Todo -o Components/Pages
前のコマンドの -n|--name
オプションで、新しい Razor コンポーネントの名前を指定します。 新しいコンポーネントは、-o|--output
オプションを使用してプロジェクトの Components/Pages
フォルダーに作成されます。
dotnet new razorcomponent -n Todo -o Pages
前のコマンドの -n|--name
オプションで、新しい Razor コンポーネントの名前を指定します。 新しいコンポーネントは、-o|--output
オプションを使用してプロジェクトの Pages
フォルダーに作成されます。
重要
Razor コンポーネント ファイル名の先頭文字は、大文字である必要があります。 Pages
フォルダーを開き、Todo
コンポーネントのファイル名の先頭が大文字 T
であることを確認します。 ファイル名は Todo.razor
のはずです。
任意のファイル エディターで Todo
コンポーネントを開き、ファイルの先頭で次の変更を行います。
- 相対 URL
/todo
とともに@page
Razor ディレクティブを追加します。 - そのまま静的にレンダリングされないように、ページの対話機能を有効にします。 対話型サーバー レンダリング モードにすると、コンポーネントでサーバーからの UI イベントを処理できます。
- ページに HTML
<title>
要素を追加することを可能にするPageTitle
コンポーネントを使用してページ タイトルを追加します。
任意のファイル エディターで Todo
コンポーネントを開き、ファイルの先頭で次の変更を行います。
- 相対 URL
/todo
とともに@page
Razor ディレクティブを追加します。 - ページに HTML
<title>
要素を追加することを可能にするPageTitle
コンポーネントを使用してページ タイトルを追加します。
任意のファイル エディターで Todo
コンポーネントを開き、相対 URL /todo
とともに @page
Razor ディレクティブを追加します。
Todo.razor
:
@page "/todo"
@rendermode InteractiveServer
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
@code {
}
@page "/todo"
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
@code {
}
@page "/todo"
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
@code {
}
@page "/todo"
<h3>Todo</h3>
@code {
}
@page "/todo"
<h3>Todo</h3>
@code {
}
Todo.razor
ファイルを保存します。
ナビゲーション バーに Todo
コンポーネントを追加します。
NavMenu
コンポーネントはアプリのレイアウトで使用されます。 レイアウトは、アプリ内でのコンテンツの重複を回避できるようにするコンポーネントです。 アプリによってコンポーネントの URL が読み込まれるときに、NavLink
コンポーネントによりそのアプリの UI でキューが指定されます。
NavMenu
コンポーネントのナビゲーション要素 (<nav>
) コンテンツに、次に示す Todo
コンポーネントの <div>
要素を追加します。
Components/Layout/NavMenu.razor
:
Shared/NavMenu.razor
:
<div class="nav-item px-3">
<NavLink class="nav-link" href="todo">
<span class="oi oi-list-rich" aria-hidden="true"></span> Todo
</NavLink>
</div>
NavMenu.razor
ファイルを保存します。
TodoList
フォルダーからコマンド シェルで dotnet watch run
コマンドを実行して、アプリをビルドして実行します。 アプリが実行された後、そのアプリのナビゲーション バーにある [Todo
] リンクを選択して、新しい Todo ページにアクセスします。これにより、/todo
にページが読み込まれます。
アプリでコマンド シェルを実行したままにします。 ファイルが保存されるたび、アプリは自動的にリビルドされ、ブラウザーのページは自動的に再度読み込まれます。
Todo アイテムを表すクラスを保持するために、プロジェクト (TodoList
フォルダー) のルートに TodoItem.cs
ファイルを追加します。 TodoItem
クラス用に次の C# コードを使います。
TodoItem.cs
:
namespace BlazorSample;
public class TodoItem
{
public string? Title { get; set; }
public bool IsDone { get; set; }
}
public class TodoItem
{
public string? Title { get; set; }
public bool IsDone { get; set; }
}
public class TodoItem
{
public string? Title { get; set; }
public bool IsDone { get; set; }
}
public class TodoItem
{
public string Title { get; set; }
public bool IsDone { get; set; }
}
public class TodoItem
{
public string Title { get; set; }
public bool IsDone { get; set; }
}
注意
TodoItem.cs
ファイルと TodoItem
クラスを作成するために Visual Studio を使用している場合は、次の "いずれか" の方法を使用します。
- Visual Studio によってクラス用に生成される名前空間を削除します。
- 前のコード ブロックの [コピー] ボタンを使用し、Visual Studio によって生成されるファイルの内容全体を置き換えます。
Todo
コンポーネントに戻り、次のタスクを実行します。
- Todo アイテム用のフィールドを
@code
ブロックに追加します。Todo
コンポーネントでは、このフィールドを使って ToDo リストの状態を維持します。 - 各 Todo アイテムをリスト アイテム (
<li>
) としてレンダリングするために、順序のないリストのマークアップとforeach
ループを追加します。
Components/Pages/Todo.razor
:
@page "/todo"
@rendermode InteractiveServer
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
@code {
private List<TodoItem> todos = new();
}
Pages/Todo.razor
:
@page "/todo"
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
@code {
private List<TodoItem> todos = new();
}
Pages/Todo.razor
:
@page "/todo"
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
@code {
private List<TodoItem> todos = new();
}
Pages/Todo.razor
:
@page "/todo"
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
@code {
private List<TodoItem> todos = new();
}
Pages/Todo.razor
:
@page "/todo"
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
@code {
private IList<TodoItem> todos = new List<TodoItem>();
}
アプリには、リストに Todo 項目を追加するための UI 要素が必要です。 順序のないリスト (<ul>...</ul>
) の下に、テキスト入力 (<input>
) とボタン (<button>
) を追加します。
@page "/todo"
@rendermode InteractiveServer
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
<input placeholder="Something todo" />
<button>Add todo</button>
@code {
private List<TodoItem> todos = new();
}
@page "/todo"
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
<input placeholder="Something todo" />
<button>Add todo</button>
@code {
private List<TodoItem> todos = new();
}
@page "/todo"
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
<input placeholder="Something todo" />
<button>Add todo</button>
@code {
private List<TodoItem> todos = new();
}
@page "/todo"
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
<input placeholder="Something todo" />
<button>Add todo</button>
@code {
private List<TodoItem> todos = new();
}
@page "/todo"
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
<input placeholder="Something todo" />
<button>Add todo</button>
@code {
private IList<TodoItem> todos = new List<TodoItem>();
}
TodoItem.cs
ファイルと更新された Todo.razor
ファイルを保存します。 コマンド シェルでは、ファイルが保存されるとアプリが自動的に再構築されます。 ブラウザーによってページが再度読み込まれます。
Add todo
ボタンを選択しても何も起こりません。ボタンにイベント ハンドラーがアタッチされていないためです。
Todo
コンポーネントに AddTodo
メソッドを追加し、@onclick
属性を使用して、そのメソッドをボタン用に登録します。 ボタンを選択すると C# のメソッド AddTodo
が呼び出されます。
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>
@code {
private List<TodoItem> todos = new();
private void AddTodo()
{
// Todo: Add the todo
}
}
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>
@code {
private List<TodoItem> todos = new();
private void AddTodo()
{
// Todo: Add the todo
}
}
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>
@code {
private List<TodoItem> todos = new();
private void AddTodo()
{
// Todo: Add the todo
}
}
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>
@code {
private List<TodoItem> todos = new();
private void AddTodo()
{
// Todo: Add the todo
}
}
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>
@code {
private IList<TodoItem> todos = new List<TodoItem>();
private void AddTodo()
{
// Todo: Add the todo
}
}
新しい Todo アイテムのタイトルを取得するには、@code
ブロックの先頭に newTodo
文字列フィールドを追加します。
private string? newTodo;
private string newTodo;
@bind
属性を使用して newTodo
をバインドするようにテキストの <input>
要素を変更します。
<input placeholder="Something todo" @bind="newTodo" />
指定したタイトルを備えた TodoItem
をリストに追加するように、AddTodo
メソッドを更新します。 newTodo
を空の文字列に設定して、テキスト入力の値をクリアします。
@page "/todo"
@rendermode InteractiveServer
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
<ul>
@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;
}
}
}
@page "/todo"
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
<ul>
@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;
}
}
}
@page "/todo"
<PageTitle>Todo</PageTitle>
<h3>Todo</h3>
<ul>
@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;
}
}
}
@page "/todo"
<h3>Todo</h3>
<ul>
@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;
}
}
}
@page "/todo"
<h3>Todo</h3>
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>
@code {
private IList<TodoItem> todos = new List<TodoItem>();
private string newTodo;
private void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
}
Todo.razor
ファイルを保存します。 アプリはコマンド シェルで自動的にリビルドされ、ページはブラウザーで再度読み込まれます。
各 Todo アイテムのタイトルのテキストは編集可能にすることができます。また、チェックボックスはユーザーが完了したアイテムを追跡するのに役立ちます。 各 Todo アイテムにチェックボックス入力を追加し、その値を IsDone
プロパティにバインドします。 @todo.Title
を、@bind
で todo.Title
にバインドされた <input>
要素に変更します。
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="todo.Title" />
</li>
}
</ul>
<h3>
ヘッダーを更新し、完了していない (IsDone
が false
の) Todo アイテムの数のカウントを表示するようにします。 次のヘッダーの Razor 式は、Blazor がコンポーネントを再レンダリングするたびに評価されます。
<h3>Todo (@todos.Count(todo => !todo.IsDone))</h3>
完成した Todo
コンポーネント:
@page "/todo"
@rendermode InteractiveServer
<PageTitle>Todo</PageTitle>
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="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;
}
}
}
@page "/todo"
<PageTitle>Todo</PageTitle>
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="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;
}
}
}
@page "/todo"
<PageTitle>Todo</PageTitle>
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="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;
}
}
}
@page "/todo"
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="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;
}
}
}
@page "/todo"
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="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;
}
}
}
Todo.razor
ファイルを保存します。 アプリはコマンド シェルで自動的にリビルドされ、ページはブラウザーで再度読み込まれます。
アイテムを追加し、アイテムを編集し、Todo アイテムに完了のマークを付けて、コンポーネントをテストします。
完了したら、コマンド シェルでアプリをシャットダウンします。 多くのコマンド シェルでは、Ctrl+C (Windows) または ⌘+C (macOS) キーボード コマンドを使用してアプリを停止できます。
Azure に発行する
Azure へのデプロイについては、「クイックスタート: ASP.NET Web アプリをデプロイする」を参照してください。
次のステップ
このチュートリアルでは、次の作業を行う方法を学びました。
- Todo リストの Blazor アプリ プロジェクトを作成する
- Razor コンポーネントを変更する
- コンポーネントでイベント処理とデータ バインディングを使用する
- Blazor アプリでルーティングを使用する
ASP.NET Core Blazor 用のツールについて学習します。
ASP.NET Core