Phoenix1.7 自作した関数コンポーネントを<.関数名>で呼び出す

こんにちは！
プログラミング未経験文系出身、Elixirの国に迷い込んだ？！見習いアルケミストのaliceと申します。
今回はform_components.exから自作の関数コンポーネント[^0]を呼び出すときに `<.関数名>`で呼び出す方法を学びました。

■「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)



# 目的
前回は自作の関数コンポーネントmy_components.exを作りました。
しかし、使用する際にモジュール名を指定しないと呼び出せない状態になっています。
```elixir:form_components.ex
<Mycomponents.input field={@form[:message]} type="textarea" label="Message" />
```
そこで、以下のように、`<.関数名>`で呼び出して、見やすいコードにしたい。
```elixir:form_components.ex
<.input field={@form[:message]} type="textarea" label="Message" />
```

前回の記事はこちら

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


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


# 仮説
- my_components.ex
└関数名がinputのままだと`CoreComponents.input/1`と干渉してしまうので、`Mycomponents.input/1`の関数名を変更するのではないか？

- contact_web.ex
└`html_helpers`に`import ContactWeb.Mycomponents`と書き込むのではないか？[^1]


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


## 1. Mycomponents.input/1の関数名を変更する
関数名がinputのままだとCoreComponents.input/1と干渉してしまうので、Mycomponents.input/1の関数名を変更します。

```diff_elixir:my_components.ex
-  def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
+  def textarea(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
     assigns
     |> assign(field: nil, id: assigns.id || field.id)
     |> assign(:errors, Enum.map(field.errors, &CoreComponents.translate_error(&1)))
     |> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end)
     |> assign_new(:value, fn -> field.value end)
-    |> Mycomponents.input()
+    |> Mycomponents.textarea()
  end
```

```diff_elixir:my_components.ex
-  def input(%{type: "textarea"} = assigns) do
+  def textarea(%{type: "textarea"} = assigns) do
    ~H"""
    <div phx-feedback-for={@name}>
      <CoreComponents.label for={@id}><%= @label %></CoreComponents.label>
      <textarea
        id={@id}
        name={@name}
        rows={@rows}
        class={[
          "mt-2 block w-full rounded-lg text-zinc-900 focus:ring-0 sm:text-sm sm:leading-6",
          "phx-no-feedback:border-zinc-300 phx-no-feedback:focus:border-zinc-400 bg-green-500/50",
          @errors == [] && "border-zinc-300 focus:border-zinc-400",
          @errors != [] && "border-rose-400 focus:border-rose-400"
        ]}
        {@rest}
      ><%= Phoenix.HTML.Form.normalize_value("textarea", @value) %></textarea>
      <CoreComponents.error :for={msg <- @errors}><%= msg %></CoreComponents.error>
    </div>
    """
  end
```

## 2. html_helpersに自作した関数コンポーネントのimport文を書き込む
```diff_elixir:contact_web.ex
   defp html_helpers do
       quote do
         # HTML escaping functionality
         import Phoenix.HTML
         # Core UI components and translation
         import ContactWeb.CoreComponents
         import ContactWeb.Gettext
+        import ContactWeb.Mycomponents

         # Shortcut for generating JS commands
         alias Phoenix.LiveView.JS

         # Routes generation with the ~p sigil
         unquote(verified_routes())
       end
     end
```

## 3. <.関数名>で呼び出す
```diff_elixir:form_components.ex
- <Mycomponents.input field={@form[:message]} type="textarea" label="Message" />
+ <.textarea field={@form[:message]} type="textarea" label="Message" />
```

# できました(^▽^)/
<.関数名>で自作の関数コンポーネントを呼び出せています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677280/4a0ce485-0996-f64d-6184-55f117582fe0.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


[^0]: 背景色が`bg-green-500/50`のtextareaをrenderする関数です。

[^1]: その仮説を考えた理由は、html_helpersに記載すると、全てのHTMLビューにおいてmy_components.exがimportされるので、何度もimport文を書かなくていいのでは？と考えたからです。 https://zenn.dev/koga1020/books/phoenix-guide-ja-1-7/viewer/components#%E3%82%B3%E3%82%A2%E3%82%B3%E3%83%B3%E3%82%BB%E3%83%97%E3%83%88

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


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