I’m not a macro expert, so maybe someone can help me understand this.
I want to define attributes in my function component from a list. I’ve used the following approach successfully with Ecto schemas in the past:
@list_of_fields ~w(field1 field2 field3 ... )a
for field_name <- @list_of_fields do
field field_name, :string
end
But when I try to do the same with a function component:
@list_of_attributes ~w(attr1 attr2 attr3 ... )a
for attr_name <- @list_of_attributes do
attr attr_name, :string
end
I get a lovely:
== Compilation error in file lib/live_select.ex ==
** (FunctionClauseError) no function clause matching in Phoenix.Component."MACRO-attr"/4
The following arguments were given to Phoenix.Component."MACRO-attr"/4:
# 1
#Macro.Env<aliases: [{ChangeMsg, LiveSelect.ChangeMsg}], context: nil, context_modules: [LiveSelect], file: "/Users/max/code/live_select/lib/live_select.ex", function: nil, functions: [{Phoenix.Component, [assign: 2, assign: 3, assign_new: 3, assigns_to_attributes: 1, assigns_to_attributes: 2, changed?: 2, dynamic_tag: 1, focus_wrap: 1, form: 1, inputs_for: 1, intersperse: 1, link: 1, live_component: 1, live_file_input: 1, live_flash: 2, live_img_preview: 1, live_render: 2, live_render: 3, live_title: 1, to_form: 1, to_form: 2, update: 3, upload_errors: 1, upload_errors: 2]}, {Kernel, [!=: 2, !==: 2, *: 2, **: 2, +: 1, +: 2, ++: 2, -: 1, -: 2, --: 2, /: 2, <: 2, <=: 2, ==: 2, ===: 2, =~: 2, >: 2, >=: 2, abs: 1, apply: 2, apply: 3, binary_part: 3, binary_slice: 2, binary_slice: 3, bit_size: 1, byte_size: 1, ceil: 1, div: 2, elem: 2, exit: 1, floor: 1, function_exported?: 3, get_and_update_in: 3, get_in: 2, hd: 1, inspect: 1, inspect: 2, is_atom: 1, is_binary: 1, is_bitstring: 1, ...]}, {Phoenix.LiveView.Helpers, [live_file_input: 2, live_img_preview: 2, live_patch: 1, live_patch: 2, live_redirect: 1, live_redirect: 2, live_title_tag: 1, live_title_tag: 2]}], lexical_tracker: #PID<0.252.0>, line: 262, macro_aliases: [], macros: [{Phoenix.Component.Declarative, [def: 2, defp: 2]}, {Phoenix.Component, [attr: 2, attr: 3, embed_templates: 1, embed_templates: 2, render_slot: 1, render_slot: 2, sigil_H: 2, slot: 1, slot: 2, slot: 3]}, {Kernel, [!: 1, &&: 2, ..: 0, ..: 2, ..//: 3, <>: 2, @: 1, alias!: 1, and: 2, binding: 0, binding: 1, dbg: 0, dbg: 1, dbg: 2, def: 1, defdelegate: 2, defexception: 1, defguard: 1, defguardp: 1, defimpl: 2, defimpl: 3, defmacro: 1, defmacro: 2, defmacrop: 1, defmacrop: 2, defmodule: 2, defoverridable: 1, defp: 1, defprotocol: 2, defstruct: 1, destructure: 2, get_and_update_in: 2, if: 2, in: 2, is_exception: 1, ...]}, {Phoenix.LiveView.Helpers, [live_component: 2, live_component: 3, render_block: 1, render_block: 2, sigil_L: 2]}], module: LiveSelect, requires: [Application, Kernel, Kernel.Typespec, Phoenix.Component, Phoenix.Component.Declarative, Phoenix.LiveView.Helpers, Phoenix.Template], ...>
# 2
{:attr_name, [line: 262], nil}
# 3
:string
# 4
[]
(phoenix_live_view 0.18.13) lib/phoenix_component.ex:1824: Phoenix.Component."MACRO-attr"/4
(phoenix_live_view 0.18.13) expanding macro: Phoenix.Component.attr/2
lib/live_select.ex:262: LiveSelect (module)
Why does it work in one case but not in the other? Is there a way to make it work?
Cheers