演習 - データ バインディングとイベント

完了

この演習では、Blazor アプリ内に基本的な Todo リスト コンポーネントを作成します。

Todo ページを作成する

  1. [Todo] ページを作成します。

    Visual Studio で、[ソリューション エクスプローラー]Components/Pages フォルダーを右クリックし、[追加]>[Razor コンポーネント] を選択します。 コンポーネントに Todo.razor という名前を付けます。

    Visual Studio Code 内で、ソリューション エクスプローラー内の [Pages] フォルダーを右クリックし、[新しいファイルの追加...]>[Razor コンポーネント] を選択します。 コンポーネントに Todo.razor という名前を付けます。 そのファイルは [Pages] フォルダー内に作成される必要があります

    重要

    Razor コンポーネント ファイル名の先頭文字は、大文字である必要があります。 Pages フォルダーを展開して、Todo コンポーネントのファイル名が大文字の T で始まっていることを確認します。 ファイル名は Todo.razor のはずです。

  2. Todo コンポーネントを開き、/todo の相対 URL を使用して、ファイルの先頭に @page Razor ディレクティブを追加します。

    @page "/todo"
    
    <h3>Todo</h3>
    
    @code {
    
    }
    
  3. Components/Pages/Todo.razor ファイルを保存します。

Todo コンポーネントをナビゲーション バーに追加する

アプリのレイアウトでは NavMenu コンポーネントを使用します。 レイアウトは、アプリ内でのコンテンツの重複を回避できるようにするコンポーネントです。 NavLink コンポーネントによって HTML アンカー タグがレンダリングされるので、アプリの URL がリンクと一致したときにアプリの UI で合図を出せるようにこのタグのスタイルを設定できます。

ソリューション エクスプローラーで Components/Layout フォルダーを展開し、NavMenu.razor ファイルを開きます。 NavMenu コンポーネントの <nav>...</nav> セクションに、次の新しい <div>...</div> と、Todo コンポーネントに対する NavLink コンポーネントを追加します。

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>

Components/Layout//NavMenu.razor ファイルを保存します。 ブラウザーが自動的に更新され、ナビゲーション バーに Todo エントリが表示されるようになりました。

追加した Todo ナビゲーション要素のスクリーンショット

Todo 項目を作成する

ソリューション エクスプローラーでプロジェクトを右クリックし、[追加]>[新しいフォルダー] を選択します。 新しいフォルダーに Data という名前を付けます。

ソリューション エクスプローラーで、Data フォルダーを右クリックしてから、[追加]>[クラス] を選択します。 新しいクラスに TodoItem.cs という名前を付けてから、[追加] を選択します。 この新しいクラスは、todo 項目を表す C# クラスを保持します。

7 行目以降のコードを、TodoItem クラス用の次の C# コードに置き換えます。 ? を使用して、Title を null 許容文字列として宣言します。 ファイルを保存します。

namespace BlazorHybridApp.Data;

public class TodoItem
{
    public string? Title { get; set; }
    public bool IsDone { get; set; } = false;
}

TodoItems のリストをバインドする

以上で、TodoItem オブジェクトのコレクションを Blazor で HTML にバインドできるようになりました。 Components/Pages/Todo.razor ファイルで以下の変更を行うことで、これを実現します。

  • @using BlazorHybridApp.Data を使用して TodoItem の using 宣言を追加します。
  • Todo アイテム用のフィールドを @code ブロックに追加します。 Todo コンポーネントでは、このフィールドを使って ToDo リストの状態を維持します。
  • 各 Todo アイテムをリスト アイテム (<li>) としてレンダリングするために、順序のないリストのマークアップと foreach ループを追加します。
@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();
}

Todo を作成するためのフォーム要素を追加する

  1. アプリには、リストに Todo 項目を追加するための UI 要素が必要です。 順序のないリスト (<ul>...</ul>) の下に、テキスト入力 (<input>) とボタン (<button>) を追加します。

    @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();
    }
    
  2. 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
        }
    }
    
  3. 新しい Todo アイテムのタイトルを取得するには、@code ブロックの先頭に newTodo 文字列フィールドを追加します。

    @code {
        private List<TodoItem> todos = new();
        private string? newTodo;
    
        // Omitted for brevity...
    }
    

    @bind 属性を使用して、newTodo をバインドするように <input> 要素を変更します。

    <input placeholder="Something todo" @bind="newTodo" />
    
  4. 指定したタイトルを備えた TodoItem をリストに追加するように、AddTodo メソッドを更新します。 newTodo を空の文字列に設定して、テキスト入力の値をクリアします。

    @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;
            }
        }
    }
    
  5. Components/Pages/Todo.razor ファイルを保存します。 アプリをリビルドして再起動します。

  6. 各 todo のタイトル テキストは編集可能にすることができ、チェックボックスは完了した項目をユーザーが追跡するのに役立ちます。 各 Todo アイテムにチェックボックス入力を追加し、その値を IsDone プロパティにバインドします。 @todo.Title を、@bindtodo.Title にバインドされた <input> 要素に変更します。

    <ul class="list-unstyled">
        @foreach (var todo in todos)
        {
            <li>
                <input type="checkbox" @bind="todo.IsDone" />
                <input @bind="todo.Title" />
            </li>
        }
    </ul>    
    
  7. <h3> ヘッダーを更新し、完了していない (IsDonefalse の) Todo アイテムの数のカウントを表示するようにします。

    <h3>Todo (@todos.Count(todo => !todo.IsDone))</h3>
    
  8. Components/Pages/Todo.razor ファイルを保存し、もう一度アプリを実行します。

  9. コンポーネントをテストするために、項目を追加し、項目を編集し、項目を完了としてマークします。

    完成した [Todo] ページのスクリーンショット