Imagine you have a core component for LiveView/Phoenix component, and it has some static component like icon
For example:
<Heroicons.inbox_stack class="w-6 h-6 mx-auto stroke-current" />
You want to load it in a loop something like this:
<.block :for={{id, title, icon_module} <- tailwind_settings} id={id} title={title}>
<icon_module class="w-6 h-6 mx-auto stroke-current" />
</.block>
How can we implement it?
Thank you in advance.
I found Phoenix.LiveView.HTMLEngine.component, but I could not use with string name of Elixir module and function like: "Elixir.Heroicons.inbox_stack"
<.block :for={{id, title, module} <- tailwind_settings} id={id} title={title}>
<%= Phoenix.LiveView.HTMLEngine.component(
String.to_existing_atom(module),
[class: "w-6 h-6 mx-auto stroke-current"],
{__ENV__.module, __ENV__.function, __ENV__.file, __ENV__.line}
) %>
</.block>
This function needs 3 arity and I can’t use apply, so String.to_existing_atom(module) is just used for converting to module
Do you have any idea?
Thanks
I did like this, finally see it works:
<.block :for={{id, title, module} <- tailwind_settings} id={id} title={title}>
<%= Phoenix.LiveView.HTMLEngine.component(
Code.eval_string("&#{module}/1") |> elem(0),
[class: "w-6 h-6 mx-auto stroke-current"],
{__ENV__.module, __ENV__.function, __ENV__.file, __ENV__.line}
) %>
</.block>
If you have another way, please let me know
Thanks
Function.capture/3 is what you’re looking for.
LostKobrakai:
Function.capture
I tried this, I have full name of module and its function which is like this: "Heroicons.inbox_stack", but it needs to have module and function name separately.
I’d suggest changing the input then to e.g. provide the function name only. Or the module and function name separately.
Yes, you’re right, I just have one question,
<.block :for={{id, title, module} <- tailwind_settings} id={id} title={title}>
<%= Phoenix.LiveView.HTMLEngine.component(
Code.eval_string("&#{module}/1") |> elem(0),
[class: "w-6 h-6 mx-auto stroke-current"],
{__ENV__.module, __ENV__.function, __ENV__.file, __ENV__.line}
) %>
</.block>
This code is working now, I have no problem. The module is hard-coded, and I do not get it from user input, with these situations I am going to face with security issue?
Hey all! It seems that HTMLEngine.component is no longer there… does anyone have another way of dynamically render a component?
You rock @LostKobrakai ! Thanks a lot! I need to find a “public” api to do this before it changes again.