Blazor Client-Sideアプリで、帳票印刷アプリケーションの作成をしてみたいと思います。
今回は、paper.cssを使ってブラウザだけで名刺を印刷するで、実現されていることをオマージュ(最大限パクリ)させて頂き、Blazorに換装してみたいと思います。
サンプルコード
https://github.com/kimux8/BlazorAppPrint
概要
参照元サイト様のBlazor版です。JavaScript + CSSにより名刺印刷アプリを実現されています。
paper.cssを使ってブラウザだけで名刺を印刷する
https://qiita.com/okoppe8/items/abcafdad3a894bca7f38
また、参照元ではCSSフレームワークであるpaper.css
を活用されています。
paper.css
https://github.com/cognitom/paper-css
そろそろ真面目に、HTMLで帳票を描く話をしようか
https://qiita.com/cognitom/items/d39d5f19054c8c8fd592
今回は、移植するにあたり、はまったところ(帳票作成とあまり関係ないことも含め)を中心に記述していきたいと思います。
ページ間でのパラメータの渡し方について
Blazorでのページ遷移はいくつかやり方がありますが、NavigationManager
のNavigateTo("リンク先")メソッド
を使用する方法があります。パラメータが複数ある場合、複数のルートパラメータ
を指定することができますが、数が多すぎる場合、必要な情報を定義したクラスをShared
に定義してInject
して連携した方がスッキリします。
ルートパラメータによるパラメータ渡し
@code{
string p0 = @"営業推進部営業1課
シニアマネージャー";
...
string p5 = @"〒100-8111
東京都千代田区千代田1-1
ロイヤルパレスパークビル 15F
電話: 03-1111-1111(代表) FAX: 03-2222-2222
携帯: 090-3333-3333
mail: kii-taichiro@dummy.lo.go.jp";
void OnPrint()
{
// カッコ悪い
navMgr.NavigateTo(string.Format("/print/{0}/{1}/{2}/{3}/{4}/{5}", p0, p1, p2, p3, p4, p5));
}
}
@page "/print/{p0}/{p1}/{p2}/{p3}/{p4}/{p5}"
Injectによるパラメータ渡し
namespace BlazorAppPrint.Shared
{
public class Person
{
public string P0 { get; set; }
public string P1 { get; set; }
public string P2 { get; set; }
public string P3 { get; set; }
public string P4 { get; set; }
public string P5 { get; set; }
....
}
}
using BlazorAppPrint.Shared;
namespace BlazorAppPrint
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<Person>(); // インスタンス化
}
}
}
@page "/"
@inject NavigationManager navMgr
@inject Person person
@code{
protected override void OnInitialized()
{
person.P0 = @"営業推進部営業1課
シニアマネージャー";
person.P1 = "きい";
...
person.P5 = @"〒100-8111
東京都千代田区千代田1-1
ロイヤルパレスパークビル 15F
電話: 03-1111-1111(代表) FAX: 03-2222-2222
携帯: 090-3333-3333
mail: kii-taichiro@dummy.lo.go.jp";
}
void OnPrint()
{
// すっきりー
navMgr.NavigateTo("/print");
}
}
@page "/print"
@inject Person person
CSS分離できない問題
Blazorでは、CSSなど静的ファイルは、wwwroot/index.html
に記述します。ここに定義すると、すべてのページで読み込まれてしまうので、特定のページだけ適用したい!というのが難しいわけですね。これは、他のフレームワークからBlazorに移行しようとしたとき、大きな壁になるかもしれません。
今回はpaper.css
のCSSフレームワークを活用しているのですが、paper.css
を特定のページに適用することができないため静的リンクしていません。その為、参照元サイトでもそうですが、paper.css
の一部をsite.css
に移植しています。
CSS Isolation in Blazor Components
https://github.com/dotnet/aspnetcore/issues/10170
はじめからある不要なスタイルの削除
帳票デザインのページでは、絶対位置指定などベタに調整することがあると思います。Blazorではデフォルトプロジェクトから作成した時に、既にsite.css
に多くのスタイルが定義された状態であり、これらの定義が邪魔になることがあります。
今回は、app
に定義されたスタイルをコメントアウトしています。
app {
/*コメントアウト*/
/*position: relative;
display: flex;
flex-direction: column;*/
}
Tableでは、子要素をコンポーネント化しない
今回のアプリケーションでは、名刺デザインが2つ(プレビュー用と印刷用)が登場しますが、Table
により実装しています。ここをサクっとコンポーネント化すれば、繰り返し処理などはスッキリするのですが、Table
と中の要素(tr,td
)を別コンポーネントする場合、下記のようなCSSでは効かないので、注意が必要です。
table.preview {
position: relative;
...
transform-origin: top;
}
table.preview td {
border: 1px solid;
...
position: relative;
}
table.preview td
を使用するときは、preview
とtd
のコンポーネントは同じコンポーネントに書く。
<table class="preview">
<tr>
<td>... ここを別コンポーネントにすると、CSSがめんどい
</tr>
</table>
既存のCSSを使いまわす場合、注意が必要ですね。
常に親ウィンドウ
印刷処理は、JavaScript
のwindow.print()
をコールしています。参照元サイトでは印刷のプレビュー画面が閉じられた後、印刷用ページのウィンドウを閉じるwindow.close()
をコールしますが、今回は親ウィンドウ自体が印刷用の画面となる為、window.close()
が使えません。その為、window.history.back(-1)
により、前画面に遷移することで、同様の動作を行っています。
...
<body>
...
<!--印刷ダイアログ表示用-->
<script>
window.printwindow = () => {
setTimeout(function () {
window.print();
// windows.close()は使えないので、ひとつ前に戻る
window.history.back(-1);
}, 200);
return true;
}
</script>
<body>
最後に
Blazorでの帳票印刷は、HTMLベースでの帳票作成が手っ取り早いです。とは言え、レポート作成のパッケージをゴリゴリ使用しているアプリケーションのBlazorへの移行などは、少々大変かもしれません。