こんにちは!
プログラミング未経験文系出身、Elixirの国に迷い込んだ?!見習いアルケミストのaliceと申します。
今回はform_components.exから自作の関数コンポーネント1を呼び出すときに <.関数名>
で呼び出す方法を学びました。
■「Phoenix1.7 関数コンポーネントで遊んでみる」シリーズの目次
① モーダル上に文字数制限無しのtextareaを作成する
|> ②Phoenix.Component.attr/3 を使って関数コンポーネントを作る
|> ③core_components.exの外に関数コンポーネントを作る
|> ④自作した関数コンポーネントを<.関数名>で呼び出す
目的
前回は自作の関数コンポーネントmy_components.exを作りました。
しかし、使用する際にモジュール名を指定しないと呼び出せない状態になっています。
<Mycomponents.input field={@form[:message]} type="textarea" label="Message" />
そこで、以下のように、<.関数名>
で呼び出して、見やすいコードにしたい。
<.input field={@form[:message]} type="textarea" label="Message" />
前回の記事はこちら
実行環境
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
と書き込むのではないか?2
結果
仮説通りでした。以下のように実施して目的を達成しました。
1. Mycomponents.input/1の関数名を変更する
関数名がinputのままだとCoreComponents.input/1と干渉してしまうので、Mycomponents.input/1の関数名を変更します。
- 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
- 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文を書き込む
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. <.関数名>で呼び出す
- <Mycomponents.input field={@form[:message]} type="textarea" label="Message" />
+ <.textarea field={@form[:message]} type="textarea" label="Message" />
できました(^▽^)/
~Elixirの国のご案内~
↓Elixirって何ぞや?と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます
↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ!私もエンジニア未経験から学習中です。
↓We Are The Alchemists, my friends!3
Elixirコミュニティは本当に優しくて温かい人たちばかり!
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。4
-
背景色が
bg-green-500/50
のtextareaをrenderする関数です。 ↩ -
その仮説を考えた理由は、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 ↩
-
@torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。 ↩