Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9529

[Blazor]コンポーネント間でのステータスのやり取り方法

$
0
0

悩んだこと

  • アラート系のメッセージ処理を各ページでゴリゴリ書くのはイケてない
  • 共通化して使いまわししたい
  • componentを作って使いまわすのにも限度があるし、MainLayout.razorで一括に処理できればいいよね
  • 親コンポーネントと子コンポーネント間のやりとりってどうやるの?

今回の解決策

State Containerを作成し、それを介すことで親子間のStatusのやり取りを行いました。Fluxの考え方に似た方法です。

できたもの

IStateMessageService.cs
interfaceIStateMessageService{stringStateMessages{get;}eventActionOnChange;voidClearStateMessages();voidSetStateMessages(stringstatusMessages);}
StateMessageService.cs
publicclassStateMessageService:IStateMessageService{publicstringStateMessages{get;privateset;}publiceventActionOnChange;publicvoidSetStateMessages(IStatusMessagesstatusMessages){StateMessages=statusMessages;NotifyStateChanged();}publicvoidClearStateMessages(){StateMessages=null;NotifyStateChanged();}privatevoidNotifyStateChanged()=>OnChange?.Invoke();}
Startup.cs
publicclassStartup{publicvoidConfigureServices(IServiceCollectionservices){// 略services.AddScoped<IStateMessageService,StateMessageService>();// 追記// 略}}
MainLayout.razor
@injectIStateMessageServiceStateMessage@implementsIDisposable<divclass="sidebar">
<NavMenu/></div><divclass="main">
<AlertMessageMessage="StateMessage.StateMessages"/><divclass="contentpx-4vh-100">
@Body</div></div>@code{protectedoverridevoidOnInitialized(){StateMessage.OnChange+=StateHasChanged;}publicvoidDispose(){StateMessage.OnChange-=StateHasChanged;}}
AlertMessage.razor
@injectIStateMessageServiceStateMessage@if(!string.IsNullOrEmpty(Message)){<divclass="alertalert-successalert-dismissible@(IsVisible?"show ":"")text-leftshadow" role="alert">
<buttontype="button"class="close" data-dismiss="alert" aria-label="Close" @onclick="OnClickCloseButton">
<spanaria-hidden="true">&times;</span></button><pclass="m-0">
@Message</p></div>}@code{[Parameter]publicstringMessage{get;set;}=string.Empty;publicboolIsVisible{get;set;}=true;privatevoidOnClickCloseButton(){IsVisible=false;Task.Run(()=>StateMessage.ClearStateMessages());}}
ChildComponent.razor
@injectIStateMessageServiceStateMessage<buttontype="button"@onclick="OnClickButton">Show</button>@code{publicvoidOnClickButton(){StateMessage.SetStateMessages("Hello world!");}}

解説

StateMessageService

DIして各コンポーネントで使っていくサービスです。StateMessageService.SetStateMessagesを使い、表示するメッセージを追加します。内部ではメッセージの追加以外に、StateMessageService.OnChangeに登録されているActionを実行しています。

後々出てきますが、このActionStateHasChangedを追加することで、Messageの内容が変わるたびにDOM更新が走るといった算段です。

Razor Component

フロント側では@injectを使いIStateMessageServiceを受けます。MainLayout.razorにメッセージ表示用のAlertMessageを配置することでどの子コンポーネントでStateMessageService.SetStateMessagesを実行してもメッセージが表示されるようにします。
AlertMessage自体はBootstrapのAlertをラップしているコンポーネントです。Messageに表示したいメッセージを渡せばいい感じに表示してくれます。

AlertMessage.razorではクローズボタンが押された時の処理として、OnClickCloseButtonを定義しています。ここでStateMessageService.ClearStateMessagesを実行することで、非表示及びステートの初期化を行っています。

いいところ

ページ遷移をしてもクローズボタンを押下されない限り表示され続けます。使いどころとしてはブラウザ上でのプッシュ通知などでしょうか? 私個人はAPIのレスポンスメッセージを表示させたりしています。
WASMでもServerSideでもどっちでも使えるところも良いですね。
javascriptを1つも書かずにここまでできるBlazorは本当にすごいと思います。革新的ですね。

悪いところ

紹介したコードではメッセージが1つだけしか表示できません。トーストのようにスタックすることができないので、そういった用途には向かないでしょう。

参考

3 Ways to Communicate Between Components in Blazor
https://chrissainty.com/3-ways-to-communicate-between-components-in-blazor/

環境

  • Visual Studio 2019 ver 16.4.2
  • TargetFramework > netstandard2.0
  • LangVersion > 7.3
  • RazorLangVersion > 3.0

Viewing all articles
Browse latest Browse all 9529

Trending Articles