Blazorでpaper.cssを使って帳票をつくる

Blazor Client-Sideアプリで、paper.cssを使って帳票印刷を行ってみたいと思います。

![jzb6b-rtc82.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/df1a5363-49c8-05b5-1179-0bd43a219f62.gif)

[Demo](https://blazorappprintcss.firebaseapp.com/)

[サンプルコード](https://github.com/kimux8/BlazorAppPrintCss)

# 概要
以前の[投稿](https://qiita.com/kimuradesu/items/e385987199b207ba78ca)に続いて、`paper.css`を使って、A4,A4横などの様々な用紙サイズの帳票デザインを作成し、ブラウザの機能で印刷までを行っていきたいと思います。

paper.css
[https://github.com/cognitom/paper-css](https://github.com/cognitom/paper-css)

そろそろ真面目に、HTMLで帳票を描く話をしようか
[https://qiita.com/cognitom/items/d39d5f19054c8c8fd592](https://qiita.com/cognitom/items/d39d5f19054c8c8fd592)

# Componentへのpaper.cssの組み込み
Blazor Client-Sideアプリケーションのデフォルトプロジェクトでは、SPAアーキテクチャがモデルになっているためか、CSSファイルなどは特定のページ(画面)だけに適用することが困難です。その為、（やり方の善し悪しは別として）無理やりですが、印刷用ページに`<style>`を使用して、CSSファイルの中身をベタ書きし、CSSが効くようにしています。スタイルに`@ `を使う場合は、Razor構文だとC#コードに認識されてしまうため、`@("") ` で囲ってあげます。

```csharp:Print.razor
@page "/print"

<style>
    // paper.min.css の中身をベタ書き！
    @("@page{margin:0}body{margin:0}.sheet{margin　・・・（略) ")
</style>
```

### .NET 6 Previewから追加された`Head`コンテンツ制御

.NET 6.0 Preview 7から、`<HeadContent>`タグによりコンポーネント単位で`<head>`コンテンツの制御ができるようになりました。

https://docs.microsoft.com/ja-jp/aspnet/core/blazor/components/control-head-content?view=aspnetcore-6.0

```html:Print.razor
@page "/print"

<style>
    // paper.min.css の中身をベタ書き！
    //👇今ままで
    @("@page{margin:0}body{margin:0}.sheet{margin　・・・（略) ")
</style>
//👇これから
<HeadContent>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paper-css/0.3.0/paper.css">
</HeadContent>
```

これで外部のStylesheetをそのまま適用できるようになりました！

### Blazor Head Element Helper ライブラリを使う

@jsakamoto さん作成の [Toolbelt.Blazor.HeadElement](https://github.com/jsakamoto/Toolbelt.Blazor.HeadElement)を使うことでも同様のことができます！素晴らしい！！

https://github.com/jsakamoto/Toolbelt.Blazor.HeadElement

```html:Print.razor
@page "/print"

<style>
    //👇今ままで
    // paper.min.css の中身をベタ書き！
    @("@page{margin:0}body{margin:0}.sheet{margin　・・・（略) ")
</style>
//👇Toolbelt.Blazor.HeadElement の記入方法
<Link Rel="stylesheet" Href="https://cdnjs.cloudflare.com/ajax/libs/paper-css/0.3.0/paper.css"/>
```

#  `<body> ` にCSSクラスを動的に追加・削除
Blazor Client-Sideアプリケーションのデフォルトプロジェクトでは、初めからスタイル定義が組み込まれています。しかし、適用したいCSSフレームワークなどにより、`<body>`といったタグに、ユーザースタイルを適用したい場合があります。`paper.css`では`<body>`にページサイズを示すクラスを追加しているため、JavaScriptにより動的に追加しています。

Componentの`OnParameterSet()`を使って、`<body>`にCSSクラスを追加します。また、ページ遷移が発生する際に`IDisposable.Dispose()`が実行されるようにし、`<body>`から追加したCSSクラスが削除されるようにします。`<body>`はアプリケーション全体で共通の為、必ず削除されるようにします。

```html:wwwroot/index.html
    <script>
        window.addClass = (size, islandscape) => {
        document.body.classList.add(size);
            if (islandscape == "true") {
                document.body.classList.add("landscape");
            }
            return true;
        }
    <script>
```


```csharp:Print.razor
@inject IJSRuntime JSRuntime
@implements IDisposable
～
@code{
    protected override void OnParametersSet()
    {
        JSRuntime.InvokeAsync<bool>("addClass", new[] { prtSetting.PageSize, prtSetting.IsLandscape });
    }
    void IDisposable.Dispose()
    {
        JSRuntime.InvokeAsync<bool>("removeClass", new[] { prtSetting.PageSize, prtSetting.IsLandscape });
    }
}
```


# 不要なスタイルの無効化
デフォルトプロジェクトでは、`site.css`やbootstrapなど、はじめからあるスタイルにより、思うように画面レイアウトや印刷画面が表示されないことがあります。ここでは、印刷用ページに、特定のスタイルを`<style>`を使って初期化(`initial`)や上書きを行って無効化して対応しました。

```csharp:Print.razor
<style>
    /* site.css　スタイルの無効化 */
    @("app{position:initial; display:initial;flex-direction:initial}")
    /* Bootstrap.min.css スタイルの無効化*/
    @("@media print { body { width: 210mm;min-width: auto !important;}}")
</style>
```

# 参照サイト
[ChromeでBootstrapな画面を印刷するとなんか小さい...](https://qiita.com/qoAop/items/bd7023f99c4f267ea5f1)