ExcelからElixir入門⑫：LiveViewのコード内HTMLをテンプレートファイルに分離

【本コラムは、2分で読めて、5分くらいでお試しいただけます】
[piacere](https://twitter.com/piacere_ex)です、ご覧いただいてありがとございます :bow:

[前回](https://qiita.com/piacere_ex/items/21b0e308a36e486d8b25)に引き続き、Phoenix LiveViewのAPI無しSPAをいじっていきます

今回は、LiveViewでグラフを扱う前段として、LiveView用HTMLをテンプレートファイルに分離する方法について解説します

なお、[「Phoenix」](https://qiita.com/piacerex/items/b7787580fce5f148242f#phoenix%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)は、ElixirのWebフレームワークです

**■「ExcelからElixir入門」シリーズの目次**
[**①データ並替え／絞り込み**](https://qiita.com/piacere_ex/items/6714e1440e3f25fb46a1)
|> [**②データ列抽出、Web表示**](https://qiita.com/piacere_ex/items/b7787580fce5f148242f)
|> [<b>③WebにDBデータ表示</b>](https://qiita.com/piacere_ex/items/a7558adc6856e3577dc6)
|> [<b>④Webに外部APIデータ表示</b>](https://qiita.com/piacere_ex/items/4c212615a4eb699dd109)
|> [<b>⑤Webにグラフ表示</b>](https://qiita.com/piacere_ex/items/290b76b76d5ff8e019bf)
|> [**⑥SPAからPhoenix製APIを呼び出す（表示編）【LiveView版】**](https://qiita.com/piacerex/items/64e77b85bfb4c6832662)
|> [**⑦SPAからPhoenix製APIを呼び出す（更新編）【LiveView版】**](https://qiita.com/piacerex/items/78ee0d2ad8cca0927980)
|> [<b>⑧Gigalixirに本番リリース</b>](https://qiita.com/piacerex/items/1a9cbcc740ca3707eaec)
|> [**⑨Elixir／PhoenixのCRUD Webアプリをリリース**](https://qiita.com/piacerex/items/511f24888c7350639d0b)
|> [**⑩「LiveView」ElixirサーバサイドのみでReact的SPA／リアルタイムUIが作れる**](https://qiita.com/piacerex/items/3f8ee18c9443d63955bf)
|> [**⑪LiveView製Qiita検索SPAをフォームsubmitスタイルに換装**](https://qiita.com/piacerex/items/21b0e308a36e486d8b25)
|> [**⑫LiveViewのコード内HTMLをテンプレートファイルに分離**](https://qiita.com/piacerex/items/5b1aabb0c45bb9934bb9)
|> [**⑬ElixirサーバサイドSPAをスマホで見るためにGigalixirリリース**](https://qiita.com/piacerex/items/583174d72e6fc0cd289e)
|> [**⑭Gigalixir上のLiveViewアプリに独自ドメイン名を付与して正式なアプリ公開**](https://qiita.com/piacerex/items/b61348c282395167fd8c)

# LiveViewモジュールのredner()ではHTMLが見づらい

LiveViewモジュールのredner()は、`~L` で始まるHTMLを定義していますが、HTMLのサイズが大きくなると見通しが悪くなり、更にHTMLのコードハイライトができなくて見づらい（ここは利用するエディタ次第ですが）という問題が出てきます

```elixir:lib/basic_web/live/qiita_search_realtime.ex
defmodule BasicWeb.QiitaSearchRealtime do
  use Phoenix.LiveView

  def render(assigns) do
    ~L"""
      <p>
      <%= if @message do %><%= @message %><% end %>
      </p>

      <form phx-change="change">
      <input type="text" name="query" value="<%= @query %>" placeholder="empty" />
      …
    """
  end
…
```

# HTMLをテンプレートファイルに分離

そこで、LiveView用HTMLを、テンプレートファイルとして分離することで、HTMLのサイズが大きくなっても、コードハイライトを個別に可能とし、Phoenix通常テンプレート（.eexファイル）と同様に、見通し良くしてみましょう

## １）.heexファイル用ビューを追加

上記フォルダを参照するビューを追加します

```elixir:lib/basic_web/views/live_view.ex
defmodule BasicWeb.LiveView do
  use BasicWeb, :view
end
```

## ２）.heexファイルを置くtemplatesフォルダを作成

.heexファイルを置くためのフォルダを、既存のpageフォルダとは別に作成します

```
mkdir lib/basic_web/templates/live
```

## ３）LiveViewモジュールから.heexファイルに分離

これで.heexファイルを置く準備ができましたので、LiveViewモジュールのredner()に記述されているHTMLを、.heexファイルに分離します

なお、ちゃんとテンプレート化できたか判別するために、上部にh2タグを追加しておきます

```erb:lib/basic_web/templates/live/qiita_search_realtime.html.heex
<h2>.heexテンプレート化したLiveViewアプリ</h2>
<p>
<%= if @message do %><%= @message %><% end %>
</p>

<form phx-submit="submit" phx-change="change">
<input type="text" name="query" value={@query} placeholder="empty" readonly={if @loading, do: "readonly"} />
Query: <%= @query %><br>
<input type="submit" value="search" onclick="blur()" />
</form>

<table>
<tr>
  <th>ID</th>
  <th>タイトル</th>
  <th>作成日</th>
</tr>
<%= for result <- @results do %>
<tr>
  <td><%= result["id"] %></td>
  <td><%= result["title"] %></td>
  <td><%= result["created_at"] %></td>
</tr>
<% end %>
</table>
```

## ４）.heexファイルをテンプレートとして読み込む

最後に、LiveViewモジュールのredner()を、上記で分離した.heexファイルをテンプレートとして読み込む記述に変更し、`~L` で始まるHTMLを削除します

```diff_elixir:lib/basic_web/live/qiita_search_realtime.ex
defmodule BasicWeb.QiitaSearchRealtime do
  use Phoenix.LiveView

+ def render(assigns), do: BasicWeb.LiveView.render("qiita_search_realtime.html", assigns)
- def render(assigns) do
-   ~L"""
-     <p>
-     <%= if @message do %><%= @message %><% end %>
-     </p>
-
-     <form phx-change="change">
-     <input type="text" name="query" value="<%= @query %>" placeholder="empty" />
-     Query: <%= @query %><br>
-     </form>
-
-     <table>
-     <tr>
-       <th>ID</th>
-       <th>タイトル</th>
-       <th>作成日</th>
-     </tr>
-     <%= for result <- @results do %>
-     <tr>
-       <td><%= result["id"] %></td>
-       <td><%= result["title"] %></td>
-       <td><%= result["created_at"] %></td>
-     </tr>
-     <% end %>
-     </table>
-   """
- end
…
```

ブラウザで「``http://localhost:4000/realtime``」にアクセスしてください
![image.png](https://qiita-image-store.s3.amazonaws.com/0/155423/20088637-9ac6-2c70-ef8c-e5ea555b09c0.png)

検索をしても問題無いことが確認できました
![image.png](https://qiita-image-store.s3.amazonaws.com/0/155423/2c2c2571-edae-ee1b-9bb4-bf752410fae0.png)

# 【参考】本コラムの検証環境

本コラムは、以下環境で検証しています（恐らくUbuntu実機やMacでも動きます）

- Windows 10
  - 実機＋Elixir 1.14.2 (Erlang/OTP 25)
    - Phoenix 1.6.15
  - WSL2／Ubuntu 20.04＋Elixir 1.14.2 (Erlang/OTP 25)　※[**最新版のインストール手順はコチラ**](https://qiita.com/piacerex/items/01e89435af0f7a454ad2)
    - Phoenix 1.6.15
  - Docker／Debian 11.6＋Elixir 1.14.2 (Erlang/OTP 25)
    - Phoenix 1.6.15

- Windows11
  - WSL2／Ubuntu 22.04＋Docker Compose＋Elixir 1.13.4 (Erlang/OTP 25)
    - Phoenix 1.6.15

# 終わり

今回は、LiveView用HTMLをテンプレートファイルに分離する方法について解説しました

これでグラフ等の複雑なHTMLを書いても、見通しが悪くなることは無くなりました

[次回は、**このLiveViewアプリをGigalixirにリリース** します](https://qiita.com/piacerex/items/583174d72e6fc0cd289e)