phx.gen.htmlの使い方+おまけ

# `phx.gen.html`の使い方

- [`phx.gen.html`の使い方](#phxgenhtmlの使い方)
  - [使い方](#使い方)
  - [resources](#resources)
- [LiveViewを使用する場合と使用しない場合の違い](#liveviewを使用する場合と使用しない場合の違い)
  - [リダイレクト(クライアント側)](#リダイレクトクライアント側)
    - [コントローラーを使用する場合](#コントローラーを使用する場合)
    - [LiveViewを使用する場合](#liveviewを使用する場合)
  - [リダイレクト(サーバー側)](#リダイレクトサーバー側)
    - [別のLiveViewへリダイレクト](#別のliveviewへリダイレクト)
    - [それ以外](#それ以外)
  - [Phoenix.LiveView.JSでパッチ処理を行う](#phoenixliveviewjsでパッチ処理を行う)


## 使い方
`phx.gen.live`と異なり、<font color="red">コントローラとHTMLビューの生成</font>を行う。

以下のように実行する。

形式: `mix phx.gen.html コンテキスト スキーマ テーブル フィールド:型`

以下のファイルが生成される。

* `*_controller.ex` - コントローラー
* `*_html.ex` - ビュー
* `/*_html`
* `/*_html/*.html.heex` - テンプレート

このあと実行後の画面の指示に従い、`resources`でルートを生成する。

## resources

ルートを記述する際は、基本的に<font color="red">HTTP動詞と同じ名前のマクロ</font>を使用して定義する。

* `get`
* `post`
* `put`
* `patch`
* `delete`

`phx.gen.html`を実行した場合、これを自動で記述してくれるものが
<font color="red">`resources`</font>というマクロである。

なお、実際には`scope`に以下を記述したルートが設定されている。。

```elixir
# resources "/users", UserController を記述したのと一緒

get "/users", UserController, :index
get "/users/:id/edit", UserController, :edit
get "/users/new", UserController, :new
get "/users/:id", UserController, :show
post "/users", UserController, :create
patch "/users/:id", UserController, :update
put "/users/:id", UserController, :update
delete "/users/:id", UserController, :delete
```

# LiveViewを使用する場合と使用しない場合の違い

## リダイレクト(クライアント側)

phoenixではリダイレクトを使用する場合、次のものが記述できる。

* `<.link navigate={~p"ルート"}>`
    * `<.link herf={~p"ルート"} method="アクション">`
* `<.link patch={~p"ルート"}>`

LiveViewを使用する場合、コントローラを使用する(LiveViewを使用しない)場合のいずれも`<link navigate={~p"ルート"}>`の記述を使用することができる。

しかし他の記述において、LiveViewを使用する場合と、Controllerを使用する場合で使用できるものが異なる。

### コントローラーを使用する場合

コントローラーを使用する場合、`<link patch={~p"ルート"}>`で<font color="red">差分更新は行われない</font>。

なぜならコントローラでは<font color="red">リクエストごとにページが再レンダリング</font>されるからである。

よってControllerでは`<link patch={~p"ルート"}>`を使わない。
なぜなら、データは差分更新されず、値の再取得が行われ、<font color="red">パッチ処理が行われないから</font>である。

### LiveViewを使用する場合

LiveViewを使用する場合、各記述は同じルートでも以下のように動作が異なる。

* `<link navigate={~p"ルート"}>` - 再マウントを行う。
* `<link herf={~p"ルート"}` - ページの再取得を行う。

`<link patch={~p"ルート"}>`はパッチ処理を行う。
再マウントすることなく、<font color="red">現在のデータから差分更新</font>を行う。

差分更新のイメージは以下の通り。

```elixir
# assigns
%{
  date: ...,
  city_name: ...,
}

# 差分更新後
%{
  date: ...,
  city_name: ...,
  form: ... <- 差分更新で追加
}
```

またGET動詞しか使用できないので、`<.link herf={~p"ルート"} method="アクション">`は使用できない。

また[Javascriptによってパッチ処理を行う](#phoenixliveviewjsでパッチ処理を行う)こともできる

## リダイレクト(サーバー側)

LiveViewを用いてサーバー側でリダイレクトを行うには、次のように記述する。

なおルートの指定には2種類あり、以下の点で異なる。

* `to: "ルート` - <font color="red">アプリ内のルートを指定する場合</font>に使用する。
* `external: "URL"` - <font color="red">外部のURLを指定する場合</font>に使用する。

### 別のLiveViewへリダイレクト

```elixir
def handle_event("イベント", _value, socket) do
  {:noreply,
    socket
    |> push_navigate(to: ~p"ルート")
  }
end
```

### それ以外

```elixir
def handle_event("イベント", _value, socket) do
  {:noreply,
    socket
    |> redirect(to: "ルート")
  }
```

LiveViewを用いずサーバー側でリダイレクトを行うには、次の例のように記述する。

```elixir
# heex      : <.link href={~p"/users/link"} method="href_link">リンク</.link>
# router.ex : post "/users/link", UserController, :href_link

# user_controller.ex
def href_link(conn, _params) do  
  conn
  |> redirect(to: ~p"ルート")
end
```

## Phoenix.LiveView.JSでパッチ処理を行う

Phoenix.LiveView.JSを使用することで、JavaScriptでElixirを呼び出し、パッチ処理を行うことができる。

使用するには、以下のように記述する。

```heex
<button phx-click={JS.patch(~p"/new")}>Click</button>
```

`<link patch={~p"ルート"}>`と同様に、再マウントするすることなくURLと状態を更新する。