Phoenixで論理削除③：一覧／個別表示UIでの論理削除時グレーアウト表示切り替え

[Elixir Digitalization Implementors／fukuoka.ex／kokura.ex](https://fukuokaex.connpass.com/)のpiacereです
ご覧いただいて、ありがとうございます :bow:

[前回は、削除UIの論理削除トグル化](https://qiita.com/piacerex/items/9d32bdc3fd1955ff969c)を行いましたが、今回は、一覧UIの論理削除に伴う表示切り替えを実装したいと思います

内容が、面白かったり、役に立ったら、「LGTM」よろしくお願いします :wink:

<h3>:ocean::ocean::ocean: Advent Calendar、fukuoka.ex1位、Elixir2位達成ヽ(=´▽`=)ﾉ :ocean::ocean::ocean:</h3>

fukuoka.ex Advent Calendar、Webテクノロジーカテゴリで堂々1位 … 各コラムぜひお読みください
https://qiita.com/advent-calendar/2020/fukuokaex
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/8a22a81f-2917-6072-10bd-525e0fc24b75.png)](https://qiita.com/advent-calendar/2020/neosvr_reso)

そして、プログラミング言語カテゴリは、1位がRust、2位がElixir、3位がGoとモダン言語揃い踏みでのトップ3、熱いネー:laughing:
https://qiita.com/advent-calendar/2020/elixir
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/ea185203-c525-c778-dc10-6d2ecc391616.png)](https://qiita.com/advent-calendar/2020/elixir)

# 本コラムの検証環境

本コラムは、以下環境で検証しています（Windowsで実施していますが、Linuxやmacでも動作する想定です）

- Windows 10
- Elixir 1.11.3 　 　　　 ※<b>[最新版のインストール手順はコチラ](https://qiita.com/piacere_ex/items/6714e1440e3f25fb46a1#%E4%BA%8B%E5%89%8D%E6%BA%96%E5%82%99elixir%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)</b>
- Phoenix 1.5.7　　　　※<b>[最新版のインストール手順はコチラ](https://qiita.com/piacere_ex/items/b7787580fce5f148242f#phoenix%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)</b>
- PostgreSQL 10.1 　　 ※<b>[最新版のインストール手順はコチラ](https://qiita.com/piacere_ex/items/a7558adc6856e3577dc6#postgresql%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)</b>

# 一覧UIの論理削除対応

論理削除状態でも、一覧UI上は、通常と同じ表示なので、論理削除されたか否かが分かりにくいため、行をグレーアウトする対応を追加します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/31fdd2a0-869e-191d-5608-2aa57aeeb1d5.png)

前回、Deleteリンクを改修した直後のテンプレートは、以下の通りです

```elixir:lib/basic_web/templates/post/index.html.eex
…
<%= for post <- @posts do %>
    <% logical_delete = if post.deleted_at != nil, do: "Delete", else: "Restore"  # Add here %>
    <tr>
      <td><%= post.title %></td>
      <td><%= post.description %></td>
      <td><%= post.deleted_at %></td>

      <td>
        <span><%= link "Show", to: Routes.post_path(@conn, :show, post) %></span>
        <span><%= link "Edit", to: Routes.post_path(@conn, :edit, post) %></span>
        <!-- <span> --><%= # Comment-out after link "Delete", to: Routes.post_path(@conn, :delete, post), method: :delete, data: [confirm: "Are you sure?"] %><!-- </span> -->
        <span><%= link logical_delete, to: Routes.post_path(@conn, :delete, post), method: :delete, data: [confirm: "Are you sure?"] %></span>  <!-- Add here -->
      </td>
    </tr>
<% end %>
…
```

グレーアウトのstyleを追加して、テーブル行を論理削除状態に応じて、グレーアウトに切り替わるようにします

前回、Delete／Restoreリンク文言の切り替えで書いたif式をcase式に切り替え、logical_deleteを文言文字列からマップに変更することで対応します

```elixir:lib/basic_web/templates/post/index.html.eex
<style>
.disabled
{
  background-color: #c0c0c0;
}
</style>
…
<%= for post <- @posts do %>
    <%  # Modify start
    logical_delete = case post.deleted_at do
      nil -> %{ class: "",         link:  "Delete"  }
      _   -> %{ class: "disabled", link:  "Restore" }
    end  # Modify end %>
    <tr class="<%= logical_delete.class %>">  <!-- Modify here -->
      <td><%= post.title %></td>
      <td><%= post.description %></td>
      <td><%= post.deleted_at %></td>

      <td>
        <span><%= link "Show", to: Routes.post_path(@conn, :show, post) %></span>
        <span><%= link "Edit", to: Routes.post_path(@conn, :edit, post) %></span>
        <!-- <span> --><%= # Comment-out after  link "Delete", to: Routes.post_path(@conn, :delete, post), method: :delete, data: [confirm: "Are you sure?"] %><!-- </span> -->
        <span><%= link logical_delete.link, to: Routes.post_path(@conn, :delete, post), method: :delete, data: [confirm: "Are you sure?"] %></span>  <!-- Modify here -->
      </td>
    </tr>
<% end %>
…
```

これで、論理削除されたデータは、グレーアウトされます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/c91fc530-6a05-d515-cc10-521dc04e905f.png)

なお、一覧の元となっている下記関数は、ソート順不定が原因で、論理削除（というよりはあらゆるupdate）を行ったとき、順番が揺れ、使いにくいため、idでソート順を固定する下記改修を行っておくと良いです

```elixir:lib/basic/posts.ex
…
  def list_materials do
    Repo.all(from p in Post, order_by: p.id)
  end
…
```

# 個別表示UIの論理削除対応

一覧と同様に、個別表示UIも改修しましょう（Phoenixに慣れている方であれば、disabledをCSSファイル側でまとめましょう）

```elixir:lib/basic_web/templates/post/show.html.eex
<style>
.disabled
{
  background-color: #c0c0c0;
}
</style>

<h1>Show Post</h1>

<%  # Modify start
logical_delete = case @post.deleted_at do
  nil -> %{ class: "",         link:  "Delete"  }
  _   -> %{ class: "disabled", link:  "Restore" }
end  # Modify end %>
<ul class="<%= logical_delete.class %>">  <!-- Modify here -->
…
```

グレーアウトされました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/accf789f-01f4-21b1-42e5-40e2bc3a6535.png)

# 最後に

今回は、一覧／個別表示UIの論理削除時表示切り替えを行いました

Elixir開発の実務でも良く出てくるテクニックなので、覚えておきましょう

# p.s.このコラムが、面白かったり、役に立ったら…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/67568d54-6584-ad33-77c7-b3b3afe70287.png) や ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/f5b819ef-d655-ef72-294c-b1a9d2c5b563.png) にて、どうぞ応援よろしくお願いします:bow: