Phoenix1.7 Phoenix.Component.attr/3 を使って関数コンポーネントを作る

こんにちは！
プログラミング未経験文系出身、Elixirの国に迷い込んだ？！見習いアルケミストのaliceと申します。
今回はPhoenix.Component.attr/3を使って関数コンポーネントを作ってみました。

■「Phoenix1.7 関数コンポーネントで遊んでみる」シリーズの目次
① [モーダル上に文字数制限無しのtextareaを作成する](https://qiita.com/Alicesky2127/items/f47a236e1d10897a29b0))
|> ②[Phoenix.Component.attr/3 を使って関数コンポーネントを作る](https://qiita.com/Alicesky2127/items/55e97240ba9a97ae2ec8)
|> ③[core_components.exの外に関数コンポーネントを作る](https://qiita.com/Alicesky2127/items/c9d08c37bcc628e938f3)
|> ④[自作した関数コンポーネントを<.関数名>で呼び出す](https://qiita.com/Alicesky2127/items/0c111b8ee1fe547d20ff)


# 目的
前回作ったtextareaをレンダリングする関数コンポーネントについて、`rows="5"` から `rows={@rows}`にしたい。

前回の記事はこちら

https://qiita.com/Alicesky2127/items/f47a236e1d10897a29b0


## 実行環境
Windows 11 ＋ WSL2 ＋ Ubuntu 22.04
Elixir v1.14.3
Phoenix v1.7.3

# 仮説
core_component.ex内で以下をすればいいのでは？
1. defmoduleの直下に`@rows 値` を定義する
2. input関数のパイプにつなげて`assign(:rows, @rows)`を追加する

# 結果
以下のように実施して目的を達成しました。

## 1. attr/3とそのデフォルト値を設定する
今回は1カ所でしか`@rows`を使用しないので、input関数の直前に[Phoenix.Component.attr/3](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#attr/3)のデフォルト値に定義するだけでよかった。
```diff_elixir:core_components.ex
   attr :id, :any, default: nil
   attr :name, :any
   attr :label, :string, default: nil
   attr :value, :any
+  attr :rows, :integer, default: 2
```

## 2. :rowsの値をビューに渡す
1. を実施した時点で、assignsの中にはデフォルト値である`rows: 2`が入っている。
したがって、改めて`assign(:rows, @rows)`を使用する必要は無く、~Hシギルで囲まれたビューにrows: 2 の値を渡すことができた。

```diff_elixir:core_components.ex
 def input(%{type: "textarea"} = assigns) do
     ~H"""
     <div phx-feedback-for={@name}>
       <.label for={@id}><%= @label %></.label>
       <textarea
         id={@id}
         name={@name}
+        rows={@rows}
         class={[
...    
```

### (余談)attr/3を設定し忘れるとどうなるか
assignsに入れたはずのキーが見つからないと怒られました。
```
[error] GenServer #PID<0.637.0> terminating
** (KeyError) key :rows not found in: %{__changed__: nil, __given__: %{__changed__: nil, __given__: %{__changed__: nil, field: %Phoenix.HTML.FormField{id: "comment_message", name: "comment[message]", errors: [], field: :message, form: %Phoenix.HTML.Form{source: #Ecto.Changeset<action: nil, changes: %{}, errors: [name: {"can't be blank", [validation: :required]}, message: {"can't be blank", [validation: :required]}], data: #Contact.Comments.Comment<>, valid?: false>, impl: Phoenix.HTML.FormData.Ecto.Changeset, id: "comment", name: "comment", data: %Contact.Comments.Comment{__meta__: #Ecto.Schema.Metadata<:built, "comments">, id: nil, message: nil, name: nil, inserted_at: nil, updated_at: nil}, hidden: [], params: %{}, errors: [], options: [method: "post"], index: nil, action: nil}, value: nil}, label: "Message", type: "textarea"}, errors: [], field: nil, id: "comment_message", inner_block: [], label: "Message", multiple: false, name: "comment[message]", prompt: nil, rest: %{}, type: "textarea", value: nil}, errors: [], field: nil, id: "comment_message", inner_block: [], label: "Message", multiple: false, name: "comment[message]", prompt: nil, rest: %{}, type: "textarea", value: nil}
```

# できました(^▽^)/
`rows: 2` なので表示行が2行になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677280/bdf30334-e5fb-92de-b257-cfddd1662b8f.png)




# ～Elixirの国のご案内～
↓Elixirって何ぞや？と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます:laughing::sparkles::sparkles:

https://qiita.com/piacerex/items/09876caa1e17169ec5e1

↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ！私もエンジニア未経験から学習中です。

https://elixir-lang.info/topics/entry_column


↓[We Are The Alchemists, my friends!:bouquet:](https://qiita.com/torifukukaiou/items/6bcd5bbb80df9e594e9e "Awesome-san's Awesome article")[^10]
Elixirコミュニティは本当に優しくて温かい人たちばかり！
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。[^11]


https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian




[^10]: @torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。


[^11]: @kn339264さんの素敵なスライドをお借りしました。Elixirコミュニティはいろんな形で活動中！