LoginSignup
1
2

More than 3 years have passed since last update.

[Microsoft] 5. ルーティング を用いたアプリ内での画面遷移 - Angularチュートリアル Tour of Heroes を Blazor で再実装する

Last updated at Posted at 2020-07-26

ルーティング を用いたアプリ内での画面遷移

  • ダッシュボードビューを追加します。
  • ヒーロービューと、ダッシュボードビュー間で画面遷移させます。
  • ヒーロー名クリックで詳細画面へ遷移させます。
  • アプリの外からアプリのURLを開いたとき、該当の画面を表示させます。

Blazorのルーティング

Angularには、モジュール内での画面遷移を設定するためのルーティングモジュールがありました。
Blazorは、コンポーネントの先頭に @page "パス" と書くだけでルーティングできます。

Heroesコンポーネントをページにする

Heroes.razorファイルを移動します(移動しなくてもよいです)。

git mv BlazorTourOfHeroes/Shared/Heroes.razor BlazorTourOfHeroes/Pages/Heroes.razor

ファイルの先頭に@pageを追加してパスを設定します。

Heroes.razor
@page "/heroes"

トップページにリンクを追加する

トップページを書き換えてHeroesコンポーネントへのリンクを追加します。

リンクは<NavLink>タグを使います。

index.razor
@page "/"

<h1>Tour of Heroes</h1>

<nav>
    <NavLink href="heroes">Heroes</NavLink>
</nav>
<Message></Message>

ダッシュボードビューを追加する

Pagesディレクトリ以下にコンポーネントを作成します。

dotnet new razorcomponent -o BlazorTourOfHeroes/Pages -n Dashboard
Dashboard.razor
@page "/dashboard"
@using BlazorTourOfHeroes.Model
@using BlazorTourOfHeroes.Service
@inject IHeroService HeroService

<h3>Top Heroes</h3>
<div class="grid grid-pad">
    @foreach (var hero in heroes)
    {
      <a class="col-1-4">
        <div class="module hero">
        <h4>@hero.Name</h4>
        </div>
    </a>
    }
</div>

@code {
    private IEnumerable<Hero> heroes;

    protected override async Task OnInitializedAsync()
    {
        await GetHeroesAsync();
    }

    private async Task GetHeroesAsync()
    {
        heroes = (await HeroService.GetHeroes()).Take(5);
    }
}

内容はHeroesコンポーネントととほぼほぼ同じです。

LINQを使用して、先頭5つのみを取得するようにしています。

private async Task GetHeroesAsync()
{
    heroes = (await HeroService.GetHeroes()).Take(5);
}

ダッシュボードへのパス

先頭にある@pageで決めています。

@page "/dashboard"

トップページにリンクを追加する

トップページを書き換えて、ダッシュボードへのリンクを追加します。

index.razor
<h1>Tour of Heroes</h1>

<nav>
    <NavLink href="dashboard">Dashboard</NavLink>
    <NavLink href="heroes">Heroes</NavLink>
</nav>
<Message></Message>

ヒーロー詳細へのナビゲーション

以下の箇所からヒーロー詳細を表示できるようにします。

  • ダッシュボードのヒーロー
  • ヒーロー一覧のヒーロー
  • アドレスバーへ入力したURL

Heroesコンポーネントからヒーロー詳細を削除する

Heroesコンポーネントから<HeroDetail>タグを削除します。

ヒーロー詳細のパスを決める

HeroDetailコンポーネントを移動します(しなくてもよいです)。

git mv BlazorTourOfHeroes/Shared/HeroDetail.razor BlazorTourOfHeroes/Pages/HeroDetail.razor

@pageを追加します。Id:intとして、int型以外を受け取らないようにします。

HeroDetail.razor
@page "/detail/{Id:int}"

Dashboardコンポーネントからのリンク

URLにパラメータを含めるようにします。

Pages/Dashboard.razor
@foreach (var hero in heroes)
{
  <NavLink href="@("detail/" + hero.Id)" class="col-1-4">
    <div class="module hero">
    <h4>@hero.Name</h4>
    </div>
  </NavLink>
}

Heroesコンポーネントからのリンク

Heroesコンポーネントのヒーロー要素は、以下のようにクリックイベント付きの<li>になっています。置き換えます。

Pages/Heroes.razor
@foreach (var hero in heroes)
{
    <li @onclick="@(_ => OnSelect(hero))"
        class="@(selectedHero == hero ? "selected" : "")"
        ><span class="badge">@hero.Id</span> @hero.Name
    </li>    
}

foreach<li>はそのままにリンクにします。

Pages/Heroes.razor
@foreach (var hero in heroes)
{
    <li>
        <NavLink href="@("detail/" + hero.Id)">
        <span class="badge">@hero.Id</span> @hero.Name
        </NavLink>
    </li>    
}

不要になったコードを削除する(しなくてもよいです)

HeroesコンポーネントのonSelect周りの処理は不要になったので削除します。

Pages/Heroes.razor
private List<Hero> heroes;

private async Task GetHeroesAsync()
{
    heroes = await HeroService.GetHeroes();
}

protected override async Task OnInitializedAsync()
{
    await GetHeroesAsync();
}

HeroDetailコンポーネントへルーティングできるようにする

Heroesコンポーネントから HeroDetailコンポーネントのheroプロパティをセットしてヒーローを表示するようにしていました。
HeroDetailコンポーネントを変更し、URL中のID値からヒーローを表示するようにします。

HeroDetailコンポーネントでHeroServiceを使えるようにします。

Pages/HeroDetail.razor
@using BlazorTourOfHeroes.Service
@inject IHeroService HeroService

ルートパラメータからIDを受け取る

プロパティに[Parameter]をつけると、ルートパラメータを受け取れます。

HeroDetail.razor
[Parameter]
public int Id { get; set; }

受け取ったIDからヒーローを読み込みます。

Pages/HeroDetail.razor
Hero Hero { get; set; }

protected override async Task OnInitializedAsync()
{
    await GetHeroAsync();
}

private async Task GetHeroAsync()
{
    this.Hero = await HeroService.GetHeroAsync(this.Id);
}

HeroServiceGetHeroAsyncメソッドを追加する

IDから単一のヒーローを返すメソッドを追加します。

Service/HeroService.cs
public Task<Hero> GetHeroAsync(int id)
{
    // TODO: ヒーロー達を取得した __後で__ メッセージを送るようにする
    messageService.Add($"HeroService: fetched hero id={id}");
    var hero = MockHeroes.Create().FirstOrDefault(x => x.Id == id);
    return Task.FromResult(hero);
}

こんなんできました

ブラウザのアドレスバーに http://localhost:5000/detail/11 と入力します。

Dr. Niceが表示されます。

image.png

前画面に戻れるようにする

詳細から一覧やダッシュボードに戻れるようにします。

「戻る」ボタンを追加します。

Pages/HeroDetail.razor
<button @onclick="GoBackAsync">戻る</button>

AngularのようなLocationサービスはないようなので、いつものJavaScript window.history.back(-1) を呼ぶようにします。

JSRuntimeをインジェクトします。

Pages/HeroDetail.razor
@inject IJSRuntime JSRuntime

window.history.back(-1)を呼ぶようにします。

Pages/HeroDetail.razor
private async void GoBackAsync()
{
    await JSRuntime.InvokeVoidAsync("history.back", -1);
}
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2