こちらの記事の続きです。
Todoアプリに以下の機能の改造を加えます。
新しいTodoを追加したら画面に通知を表示する(
NotifyService
で別Componentの関数をKick)Todoの内容が空っぽの時は登録できないよう
Validation
を追加する
※子コンポーネントから通知を表示すればこんな回りくどいことしなくて済むのですが、お勉強目的なので目を瞑ります。
Demo
こんな感じになりました。
成果物
例によってGitHubに公開しています。
今回はsrc\2. NotifyService
以下に保存しています。
NotifyServiceについて
こちらのまんまです。
NotifierService.cs
関数を登録するNotify
イベントと、登録したイベントを発火させるUpdate
関数を持ちます。
using System; using System.Threading.Tasks; using BlazorTodo.Data; namespace BlazorTodo.Service { public class NotifierService { public async Task Update(Todo todo) { if (Notify != null) { await Notify.Invoke(todo); } } public event Func<Todo, Task> Notify; } }
Startup.cs
サービスが使えるよう、StartUp.cs
のConfigureServices
で登録します。
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
+ services.AddSingleton<NotifierService>();
services.AddBlazoredToast(); // トースト用
}
Index.razor
indexページでトーストを表示する関数を登録します。
@page "/" + @inject NotifierService Notifier @inject IToastService toastService <h1>Blazor Todo</h1> <TodoList Todos="@Todos" /> @code { IList<Todo> Todos; + string NotifyMessage { get; set; } protected override void OnInitialized() { Todos = new List<Todo>() { new Todo() { Id = Guid.NewGuid(), Content = "犬をしまう" }, new Todo() { Id = Guid.NewGuid(), Content = "お風呂に水をためる" }, new Todo() { Id = Guid.NewGuid(), Content = "水・食料を買い込む" }, new Todo() { Id = Guid.NewGuid(), Content = "避難先を確認する" }, }; + Notifier.Notify += OnNotify; } + async Task OnNotify(Todo todo) + { + await InvokeAsync( () => { + toastService.ShowInfo($"新しいTodoItem:{todo.Content}が追加されました!"); + StateHasChanged(); + }); + } + void Dispose() + { + Notifier.Notify -= OnNotify; + } }
TodoList.razor
@using System.Linq; + @inject NotifierService Notifier ... @code { [Parameter] public IList<Todo> Todos { get; set; } async void OnAddNewTodoItem(Todo todo) { if (Todos != null) { - Todos.Add(new Todo() { Id = Guid.NewGuid(), Content = newContent }); + Todos.Add(todo); + await Notifier.Update(todo); StateHasChanged(); } } ... }
Validation
こちらのまんまです。
Todo.cs
Model役のクラスに[Required]
属性を追加します。
using System;
using System.ComponentModel.DataAnnotations;
namespace BlazorTodo.Data {
public class Todo {
public Guid Id { get; set; }
public bool IsDone { get; set; }
+ [Required(ErrorMessage ="内容を空欄にはできません!")]
public string Content { get; set; }
}
}
NewItemEntry.razor
Validateを効かせるためにForm化したのとValidateが通ったとき用のHandleValidSubmit
関数を追加します。
Form化したので<input>
から@onkeypress
はなくします。
※変更点が多いのでdiff表示は止めておきます。
<EditForm class="form-inline" Model="@todoModel" OnValidSubmit="@HandleValidSubmit"> <div class="row w-100"> <DataAnnotationsValidator /> <ValidationSummary /> </div> <div class="form-group row"> <label class="col-sm-4" for="new-todo-item-content-textbox">New Todo Item</label> <input id="new-todo-item-content-textbox" class="form-control col-sm-6" placeholder="Todo Content" @bind-value="todoModel.Content" @bind-value:event="oninput"/> <button type="Add" class="col-sm-2 btn btn-primary">Submit</button> </div> </EditForm> @code { Todo todoModel = new Todo(); [Parameter] public Action<Todo> OnAddNewTodoItem { get; set; } private void HandleValidSubmit() { AddNewItem(); } void AddNewItem() { if (OnAddNewTodoItem != null) { OnAddNewTodoItem(todoModel); todoModel = new Todo(); } } }
備考:通知の表示方法
のToastを使用しています。
おわり
Validationは今まで通りって感じですね。
NotifyServiceは例によって小さく使わないと破城しそうなので注意が必要ですね。