DestroyedSoul
Custom components behave differently from core components
Hello,
In my project I need custom core components, i.e. input fields etc that are styled a bit differently. I know I can provide class for the core input component, but then it only affects the text field itself not its label.
What I tried to do is to create my own Inputs.default_input, that would behave the same way as core input, but with custom tailwind classes. I literally copied the code form the core components and adjust the looks. Everything works, except for one thing:
Let’s take email as an example. When I start typing the email, the error is displayed that it has to have @ sign. This works for both my and core components.
However, when I add the @ sign and email becomes valid, the error should disappear. Works for core component, but not for my component.
My component is added like this:
<Inputs.default_input
field={@form[:email]}
type="email"
label="Email"
placeholder="Enter email address"
/>
The implementation mirrors the core component:
... attributes ...
def default_input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
errors = if Phoenix.Component.used_input?(field), do: field.errors, else: []
assigns
|> assign(field: nil, id: assigns.id || field.id)
|> assign(:errors, Enum.map(errors, &translate_error(&1)))
|> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end)
|> assign_new(:value, fn -> field.value end)
|> default_input()
end
... non text default_inputs()...
def default_input(assigns) do
~H"""
<div class="fieldset mb-2">
<label>
<span :if={@label} class="text-base text-base-content font-normal">{@label}</span>
<input
type={@type}
name={@name}
id={@id}
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
class={[
@class || "mt-1 w-full input text-base text-base-content",
@errors != [] && (@error_class || "input-error text-base")
]}
{@rest}
/>
</label>
<.error :for={msg <- @errors}>{msg}</.error>
</div>
"""
end
The only difference is tailwind classes in the default_input().
If I keep the code literally as-is, it still doesn’t work.
def default_input(assigns) do
~H"""
<div class="fieldset mb-2">
<label>
<span :if={@label} class="label mb-1">{@label}</span>
<input
type={@type}
name={@name}
id={@id}
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
class={[
@class || "w-full input",
@errors != [] && (@error_class || "input-error")
]}
{@rest}
/>
</label>
<.error :for={msg <- @errors}>{msg}</.error>
</div>
"""
end
But it starts to work when I do this:
def default_input(assigns) do
~H"""
<.input {assigns} />
"""
end
Is there anything special about the core components that I am missing?
Marked As Solved
DestroyedSoul
While I was trying to reproduce this issue in the new repo, I found the problem.
My Inputs module was defined like this:
defmodule MyApp.Components.Inputs do
use Phoenix.Component
use MyApp, :html
...
end
:html is there to get access to translate_error(). However, I import all my custom components (indirectly) in html_helpers(). Apparently, it made a conflict even though compiler did not complain (because I import Components module, that, in its turn, has a __using__ macro that makes available other components).
I changed into:
defmodule NutrihiveWeb.Components.Inputs do
use Phoenix.Component
import MyApp.CoreComponents
...
end
and now the problem seems to have gone.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









