インフラジスティックス・ジャパン株式会社Blog

インフラジスティックス・ジャパン株式会社のチームメンバーが技術トレンド、製品Tips、サポート情報からライセンス、日々の業務から感じることなど、さまざまなトピックについてお伝えするBlogです。

オープンソース版の Ignite UI for Blazor で作る、タイルマネージャーを使ったカスタマイズ可能なダッシュボード [後編]

先日、インフラジスティックスが開発・提供する UI コンポーネントライブラリ Ignite UI の一部がオープンソース化され、MIT License のもと、商用・非商用を問わず無償で利用できるようになりました。Blazor 向けである Ignite UI for Blazor もその対象に含まれています。

そこで、本記事では Ignite UI のオープンソース化を機会に、オープンソース版の Ignite UI for Blazor に含まれるユニークなコンポーネントのひとつ、タイルマネージャーを使った、ユーザーが自分でレイアウトをカスタマイズできるダッシュボードの作成方法について解説します。

はじめに

本記事では Windows 上で Visual Studio 2026 を使用して Blazor WebAssembly アプリケーションを新規作成し、その上にオープンソース版の Ignite UI for Blazor で提供されるタイルマネージャーコンポーネントを用いたダッシュボードを構築する手順を、ステップ・バイ・ステップで解説します。

本記事はその後編です。(前編はこちら)

完成イメージ

本記事で最終的に完成するダッシュボードアプリケーションは、下図のように、ユーザーが自分でタイルを追加・削除したり、レイアウトを変更したりできるサンプルアプリケーションになります。タイルの状態はブラウザのローカルストレージに保存され、ページを再読み込みしても前回の状態が復元されます。

本記事で作成するアプリの完成イメージ - タイルマネージャーを使って自由にタイルを配置、サイズ変更をしている様子

以下のリンク先で、実際に動く様子を確認頂けます。

本記事で作成するダッシュボードアプリケーションのソースコードは以下の GitHub リポジトリで公開しています。このリポジトリには、この記事で解説している手順ごとにコミットした履歴も含まれています。

前編のおさらいと後編の内容

前編では、オープンソース版の Ignite UI for Blazor に含まれるタイルマネージャーコンポーネントを使ってユーザーが自分でレイアウトをカスタマイズできるダッシュボードを作成する方法について、基本的な操作、つまり、タイルの追加、配置とサイズの変更、削除、までを実装しました。

しかし、タイルの追加・削除、配置やサイズの変更、といった操作はすべてクライアント側で行われるため、前編までの実装ですと、ページをリロードするたびに、すべての状態が初期化されてしまいます。つまり、ページをリロードすると、先程までに追加したタイルがすべて消え失せて、真っ白なページに戻ってしまう、ということです。

そこで、本記事・後編では、前編までの実装に引き続きまして、タイルの状態をブラウザのローカルストレージに保存し、ページの再読み込み時に復元する仕組みを実装していきます。

それでは始めてまいりましょう。

タイルの状態を保存・復元する

さて、”タイルの状態” をブラウザのローカルストレージに保存・復元するわけですが、ここで "タイルの状態" とは、以下の 2 つの情報を指します。

  • 追加されているタイルの情報(TileDescriptor の集合)
  • 各タイルのサイズと配置情報

"追加されているタイルの情報" については、Home コンポーネントのフィールド変数 _tileDescriptors に格納されている単純な C# オブジェクトの集合です。これらは System.Text.Json 名前空間の JSON シリアライザーを使って JSON 文字列にシリアライズ・デシリアライズできます。

一方、"各タイルのサイズと配置情報" については、タイルマネージャーコンポーネントの SaveLayoutAsync メソッドを使って取得・LoadLayoutAsync メソッドを使って復元できます。これらのメソッドの戻り値・引数は string なので、そのままローカルストレージに保存・復元できます。

以上を踏まえて、実装していきましょう。

下準備

まず、"追加されているタイルの情報" を JSON 文字列に変換・復元するために .NET の JSON シリアライザーを使いますので、System.Text.Json 名前空間を開いておきます。Pages/Home.razor の冒頭に以下の @using ディレクティブを追加します。

@* Pages/Home.razor *@
@page "/"
@using System.Text.Json @* 👈️ System.Text.Json 名前空間を開く *@
...

続きまして、ブラウザのローカルストレージ API の呼び出しについては、JavaScript 相互運用機能を使ってこれを実現します。そのために、Home コンポーネントに IJSRuntime 型の注入プロパティを追加します。Pages/Home.razor の冒頭に @inject ディレクティブを追加してこれを行います。

@* Pages/Home.razor *@
@page "/"
@using System.Text.Json
@inject IJSRuntime JSRuntime @* 👈️IJSRuntime を注入 *@
...

また、"各タイルのサイズと配置情報" を取得・復元するには、タイルマネージャーコンポーネントのメソッドを呼び出しますから、タイルマネージャーコンポーネントの参照も必要です。そこで Pages/Home.razor の @code { } ブロック内に IgbTileManager 型のフィールド変数を追加し、@ref ディレクティブを使ってタイルマネージャーコンポーネントの参照をこのフィールド変数に取得するようにします。

@* Pages/Home.razor *@
...
<IgbTileManager @ref="_tileManager" ...

@code
{
    private IgbTileManager? _tileManager;
    ...

タイルの状態の保存

それではタイルの状態を保存するメソッド、SaveLayoutAsync を実装していきましょう。 Home コンポーネントの @code { } ブロック内に、以下のように追加します。

@* Pages/Home.razor *@
...
@code
{
    ...
    private async Task SaveLayoutAsync()
    {
        if (_tileManager is null) return;

        // "追加されているタイルの情報" を JSON 文字列に変換、
        var tileDescriptorsJson = JsonSerializer.Serialize(_tileDescriptors);
        // ローカルストレージに保存
        await JSRuntime.InvokeVoidAsync("localStorage.setItem", "tileDescriptors", tileDescriptorsJson);

        // "各タイルのサイズと配置情報" (文字列) を取得、
        var tileLayoutJson = await _tileManager.SaveLayoutAsync();
        // ローカルストレージに保存
        await JSRuntime.InvokeVoidAsync("localStorage.setItem", "tileLayout", tileLayoutJson);
    }
}

タイルが追加されたり削除されたら、この SaveLayoutAsync メソッドを呼び出すようにします。以下のように AddCounterAddEmojiRemoveTile メソッドを非同期メソッド化し、SaveLayoutAsync メソッド呼び出しを追加します。

@* Pages/Home.razor *@
...
@code
{
    ...
    private async Task AddCounter() // 👈️ void → async Task
    {
        _tileDescriptors.Add(new() { ComponentId = "Counter" });
        await SaveLayoutAsync(); // 👈️ 追加
    }

    private async Task AddEmoji() // 👈️ void → async Task
    {
        _tileDescriptors.Add(new() { ComponentId = "Emoji" });
        await SaveLayoutAsync(); // 👈️ 追加
    }

    private async Task RemoveTile(TileDescriptor descriptor) // 👈️ void → async Task
    {
        _tileDescriptors.Remove(descriptor);
        await SaveLayoutAsync(); // 👈️ 追加
    }
    ...

タイルがサイズ変更されたり配置が移動されたときは、それぞれタイルマネージャーが対応するイベント、TileDragEnd と TileResizeEnd を発生させます。これらのイベントハンドラーで SaveLayoutAsync メソッドを呼び出すように設定します。以下のように <IgbTileManager> コンポーネントに TileDragEnd および TileResizeEnd パラメーターを追加します。

@* Pages/Home.razor *@
  ...
  <IgbTileManager ...
                  TileDragEnd="SaveLayoutAsync"
                  TileResizeEnd="SaveLayoutAsync">
    ...

以上で、タイルの追加・削除や、サイズ変更・配置変更が発生するたびに、タイルの状態がブラウザのローカルストレージに保存されるようになりました。

タイルの状態の復元

次はページが初期表示されたときにタイルの状態をローカルストレージから復元するようにします。タイルの状態を復元するには、タイルマネージャーの LoadLayoutAsync メソッドを呼び出す必要がありますので、タイルマネージャーコンポーネントの参照が取得されたタイミング、つまり OnAfterRenderAsync ライフサイクルメソッドで行います。

以下のとおりの OnAfterRenderAsync の実装を Home コンポーネントの @code { } ブロック内に追加します。

@* Pages/Home.razor *@
...
@code
{
    ...
    // OnAfterRenderAsync をオーバーライドしてタイルの状態を復元
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        // 初回レンダリングであること、かつタイルマネージャー参照が取得できていることを確認
        if (firstRender && _tileManager is not null)
        {
            // タイルマネージャーの初期化完了を待機
            await _tileManager.EnsureReady();

            // ローカルストレージからタイル情報とレイアウト情報を取得
            var tileDescriptorsJson = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "tileDescriptors");
            var tileLayoutJson = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "tileLayout");

            // いずれの情報も存在する場合に復元を実行
            if (!string.IsNullOrEmpty(tileDescriptorsJson) && !string.IsNullOrEmpty(tileLayoutJson))
            {
                // "追加されているタイルの情報" を復元
                _tileDescriptors = JsonSerializer.Deserialize<List<TileDescriptor>>(tileDescriptorsJson) ?? [];

                // 再描画を起動し、各タイル (IgbTile コンポーネント) を生成
                StateHasChanged();

                // "各タイルのサイズと配置情報" を復元
                await _tileManager.LoadLayoutAsync(tileLayoutJson);
            }
        }
    }
    ...

以上で、ページが初期表示されたときに、ブラウザのローカルストレージから前回最後のタイルの状態が復元されるようになりました。

ページを再読み込みしても、最後のタイル編集結果が復元される様子

以上、前編と本記事後編とをあわせて、タイルマネージャーを使ったダッシュボードのデモンストレーションをひととおり実装できました。

お疲れさまでした。

おわりに

本記事では、オープンソース版の Ignite UI for Blazor に含まれるタイルマネージャーコンポーネントを使って、ユーザーが自分でレイアウトをカスタマイズできるダッシュボードを作成する方法について、タイルの状態のローカルストレージへの保存と復元まで実装しました。

  • タイルの配置またはサイズが変更されると、IgbTileManager コンポーネントの TileDragEnd および TileResizeEnd イベントが発生
  • タイルの配置とサイズは、IgbTileManager コンポーネントの SaveLayoutAsync メソッドで文字列として取得・LoadLayoutAsync メソッドで復元可能

前編・後編をとおして、タイルマネージャーコンポーネントを使うことで、ユーザーが自由にタイルの追加・削除、サイズ変更、配置変更を行える柔軟なダッシュボードを簡単に実装できることがお分かりいただけたかと思います。

Ignite UI の一部オープンソース化により、これまで有償版でしか利用できなかった多くのコンポーネントが無償で利用できるようになりました。その中には今回ご紹介したタイルマネージャーコンポーネントも含まれています。

なお、前編でも触れたとおり、Ignite UI シリーズは Angular、React、WebComponents 版も用意されており、それらプラットフォームでも利用可能です。これは、本記事で解説したような高度で自由度の高いレイアウト変更機能を、Blazor のみならず、Angular や React、Vue や Svelte といったライブラリ/フレームワークで構築された皆さんの Web アプリケーションに手軽に搭載できるということであり、驚くべきことです。

ぜひこの機会に Ignite UI をお試しください!

参考情報