BlazorでSPAするぞ!(3) - パラメータ - 正式版対応済

※最終更新日: 2020/5/24 正式リリース版に対応修正しました。

という事で、↓↓↓の続きです。

ryuichi111std.hatenablog.com

前回 Component の基本的な作り方・使い方を見てみましたが、今回はComponentのパラメータ機能を見ていきます。

1. パラメータ(Parameter)の利用

コンポーネントは、コンポーネント(ページ等)内にネストして配置することができました。
そして以下のように タグ で配置しました。
以下は、PersonViewerコンポーネントを .razor に配置しています(PersonViewerはPerson情報を表示するコンポーネントを想定)。

<PersonViewer />

コンポーネントではタグ属性を利用して、親(コンテナとなっているコンポーネント)から子(配置されているコンポーネント)へパラメータを渡すことができます。
以下ではPersonViewerコンポーネントに対して「ID / FirstName / LastName」の3つのパラメータを渡しています。

<PersonViewer1
  ID="@CurrentPerson.ID"
  FirstName="@CurrentPerson.FirstName"
  LastName="@CurrentPerson.LastName" />

1.1. サンプル実装

では具体的なサンプル実装を。
プロジェクトを作成します。

dotnet new blazorwasm -o component_param_blazor

(1) モデルクラスを作成

Personモデルクラスを作成します(Models/Person.cs)。

# Models/Person.cs #

using System;

namespace component_param_blazor.Models {
  public class Person {
    public int ID { get; set; }
    public string FirstName{ get; set; }
    public string LastName{ get; set; }
  }
}

(2) コンポーネントを作成

PersonViewerコンポーネントを作成します(Components/PersonViewer1.razor)。

# Components/PersonViewer1.razor #

@using component_param_blazor.Models

<div class="container">
  <div class="row">
    <div class="col-sm">ID:</div>
    <div class="col-sm">@ID</div>
  </div>
  <div class="row">
    <div class="col-sm">FirstName:</div>
    <div class="col-sm">@FirstName</div>
  </div>
  <div class="row">
    <div class="col-sm">LastName:</div>
    <div class="col-sm">@LastName</div>
  </div>
</div>

@code {
  [Parameter]
  public int ID { get; set; }
  
  [Parameter]
  public string FirstName{ get; set; }

  [Parameter]
  public string LastName{ get; set; }
}
[Parameter]

コンポーネントがらパラメータとして受け取るプロパティには [Parameter] 属性を付けます。
コンポーネントからの受取ですが、アクセス修飾子はprivateでもOKです。 (← Preview版の時はprivateで行けてた気がする)

(3) PersonViewerコンポーネントをページに配置

Pages/Index.razorにPersonViewer1コンポーネントを配置します。
Index.razorのコードブロックで Personオブジェクト を作成して、PersonViewer1コンポーネントにパラメータとして各価を引き渡します。

# Pages/Index.razor #

@page "/"
@using component_param_blazor.Components
@using component_param_blazor.Models

<PersonViewer1
  ID="@CurrentPerson.ID"
  FirstName="@CurrentPerson.FirstName"
  LastName="@CurrentPerson.LastName" />

@code {
  private Person CurrentPerson { get; set; }

  protected override void OnInitialized() {
    this.CurrentPerson = new Person() {
      ID = 0,
      FirstName = "takashi",
      LastName = "sakata" } ;
  }
}

実行画面は以下の通りです。

f:id:daigo-knowlbo:20200524144749p:plain

1.2. サンプル実装(オブジェクトとしてパラメータを渡す)

[Parameter]属性で引き渡すパラメータは、リテラル型だけでなく任意のオブジェクト型も指定可能です。
先程の PersonViewer1.razor を Personオブジェクト を受け取るように修正した版(PersonViewer2.razor)が以下です。

# Components/PersonViewer2.razor #

@using component_param_blazor.Models

<div class="container">
  <div class="row">
    <div class="col-sm">ID:</div>
    <div class="col-sm">@Person.ID</div>
  </div>
  <div class="row">
    <div class="col-sm">FirstName:</div>
    <div class="col-sm">@Person.FirstName</div>
  </div>
  <div class="row">
    <div class="col-sm">LastName:</div>
    <div class="col-sm">@Person.LastName</div>
  </div>
</div>

@code {
  [Parameter]
  public Person Person { get; set; }
}
# Pages/Index.razor #

@page "/"
@using component_param_blazor.Components
@using component_param_blazor.Models

<PersonViewer2 Person="@CurrentPerson" />

@code {
  private Person CurrentPerson { get; set; }

  protected override void OnInitialized() {
    this.CurrentPerson = new Person() {
      ID = 0,
      FirstName = "takashi",
      LastName = "sakata" } ;
  }
}

2. Cascading Parameter

親子間のプロパティの受け渡しは、前述の通りコンポーネント定義にプロパティ設定を行えば可能です。
親子関係の階層が深くなった場合に、数珠繋ぎが煩雑になることに対する解決策の1つが Cascading Parameter です。

2.1. 単純なパラメータの引き回し

まず、親から子にパラメータを引き渡す前述の方法を使った場合の、パラメータの引き回し例です。
子の配下に孫コンポーネントがあり、パラメータオブジェクトをそのまま引き継ぐ必要がある場合、↓↓↓のように実装すれば可能です。

# Pages/Index.razor #

@page "/"
@using cascading_parameter_blazor.Components

<ChildComponent YourName="@YourName" />

@code {
  private string YourName = "ryuichi111std";
}
# Components/ChildComponent.razor (子コンポーネント)#

this is Child.
<br />
@YourName
<br />
<GrandChildComponent YourName="@YourName" />

@code {
  [Parameter]
  public string YourName { get; set; }
}
# Components/GrandChildComponent.razor (個コンポーネントに配置される 孫コンポーネント)#

this is GrandChild.
<br />
@YourName

@code {
  [Parameter]
  public string YourName { get; set; }
}

2.2. Cascadingパラメータによる引き回し

が、面倒なので、Cascading Parameter機能を使えば、子孫までパラメータを一括で引き回せます。
以下が実装サンプル。

(1) 親コンポーネントの実装

# Pages/Index.razor #

@page "/"
@using component_param_blazor.Components

<div class="container bg-primary">
  <CascadingValue Value="YourName" Name="YourNameParam">
    <ChildComponent />
  </CascadingValue>
</div>

@code {
  private string YourName = "ryuichi111std";
}
【CascadingValue】

パラメータを提供するコンポーネントで「<CascadingValue>要素」を定義し、その子要素としてパラメータを引き継ぎたいコンポーネントを配置します。
Value属性値はパラメータの値。@code {} コードブロックで定義した YourName 値を渡しています。
Name属性値はパラメータ名。子孫コンポーネントValue属性で指定した@YourNameの値を YourNameParam というパラメータとして参照することができます。

(2) 子コンポーネントの実装

# Components/ChildComponent.razor #

<div class="container bg-secondary">
  this is Child.
  <br />
  @YourName
  <br />
  <GrandChildComponent />
</div>

@code {
  [CascadingParameter (Name = "YourNameParam")]
  private string YourName { get; set; }
}

【CascadingParameter属性】

プロパティ定義に対して「CascadingParameter属性」を付与します。
親要素で定義されたCascadingValueの中からYourNameParamという名前のパラメータを、自コンポーネントのYourNameプロパティの値として取得する、という意味になります。

(3) 孫コンポーネントの実装

# Components/GrandChildComponent.razor #

<div class="container bg-success">
  this is GrandChild.
  <br />
  @YourName
</div>

@code {
  [CascadingParameter (Name = "YourNameParam")]
  private string YourName { get; set; }
}

こちらも同様に「CascadingParameter」属性をプロパティに付与することでパラメータを引き継ぐことができます。

実行画面は以下の通りです。

f:id:daigo-knowlbo:20200524144723p:plain

3. まとめ

ということでComponentのパラメータでした。
(ぜんぜん、まとめじゃない・・・)

次は ryuichi111std.hatenablog.com