LoginSignup
4
1

Phoenix の input コンポーネントでCSSクラスを指定できるようにする

Last updated at Posted at 2024-03-15

Phoenix 1.7 で 導入された CoreComponent モジュールに input 関数コンポーネントがあります。mix phx.newPhoenix アプリを生成してすぐに使え、いい感じにinput 要素がスタイリングされて便利です。

しかしながら、自分でDaisyUI等を使用してinput 要素をスタイリングをしたいときに不都合が生じます。input 関数コンポーネントのCSSは直書きされており、関数呼び出し時に指定することができないのです。

対策は、2つ考えられます。

  1. input 関数コンポーネントに直書きされたCSSを好きなように調整
  2. input 関数コンポーネント実行時にclass属性を渡せるようにする

ここでは後者をやります。

やりかた

class属性を受け取れるようにする

Phoenix.Component.attr/3マクロでclass属性を明示します。型は:stringでもいいのですが、リストで渡したい時もあるので:anyとしています。

  attr :id, :any, default: nil
  attr :name, :any
  attr :label, :string, default: nil
  attr :value, :any

  attr :type, :string,
    default: "text",
    values: ~w(checkbox color date datetime-local email file month number password
               range search select tel text textarea time url week)

  attr :field, Phoenix.HTML.FormField,
    doc: "a form field struct retrieved from the form, for example: @form[:email]"

  attr :errors, :list, default: []
  attr :checked, :boolean, doc: "the checked flag for checkbox inputs"
  attr :prompt, :string, default: nil, doc: "the prompt for select inputs"
  attr :options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"
  attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"

+ attr :class, :any, default: nil

  attr :rest, :global,
    include: ~w(accept autocomplete capture cols disabled form list max maxlength min minlength
                multiple pattern placeholder readonly required rows size step)

  slot :inner_block

受け取ったclass属性を反映させる

もともとあったclass属性の値をdefault_classに切り出します。
実行時にclass属性が明示されている場合にはそれを優先するようにします。

  # All other inputs text, datetime-local, url, password, etc. are handled here...
  def input(assigns) do
+   default_class =
+     "mt-2 block w-full rounded-lg text-zinc-900 focus:ring-0 sm:text-sm sm:leading-6"
+
+   assigns = assign(assigns, class: assigns[:class] || default_class)
+
    ~H"""
    <div phx-feedback-for={@name}>
      <.label for={@id}><%%= @label %></.label>
      <input
        type={@type}
        name={@name}
        id={@id}
        value={Phoenix.HTML.Form.normalize_value(@type, @value)}
        class={[
-         "mt-2 block w-full rounded-lg text-zinc-900 focus:ring-0 sm:text-sm sm:leading-6",
+         @class,
          "phx-no-feedback:border-zinc-300 phx-no-feedback:focus:border-zinc-400",
          @errors == [] && "border-zinc-300 focus:border-zinc-400",
          @errors != [] && "border-rose-400 focus:border-rose-400"
        ]}
        {@rest}
      />
      <.error :for={msg <- @errors}><%%= msg %></.error>
    </div>
    """
  end

:tada::tada::tada:

使い方

これでDaisyUIのclassを使えるようになりました!

<.input
  field={@form[:name]}
  placeholder="Name"
  autocomplete="off"
  class="input input-bordered input-secondary mr-2"
/>

あとはお好みで調整してください。

最後に一言

本記事は 闘魂 Elixir #72 の成果です。ありがとうございます。

toukon-qiita-macbook_20230912_091808.jpg

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1