i-n-g-m-a-r

i-n-g-m-a-r

What is the expected behaviour of "phx-blur" on an input?

Steps:

  • email input component is rendered for the first time, the email input field receives focus
  • I click somewhere outside of the component, NOT the button, the email input field loses focus (blur)
  • email input field does not have focus, blur event is in the past.
  • I click the next button, blur-handler receives %{"value" => "Next"}

Is this expected behaviour?

I would expect the value in the blur-handler always to be that of the email input field.
In my mind the value of the button should be completely unrelated to the “blur”, because the button “click” did not cause the “blur”.

Render component:

def render(assigns), do: ~L"""
  <div id="<%= assigns.id %>">
    <ul>
      <li><%= email_input(assigns) %></li>
      <li><%= next_button(assigns) %></li>
    </ul>
  </div>
"""

defp email_input(assigns), do:
  Phoenix.HTML.Tag.tag :input, [
    type: "email",
    name: "email",
    value: assigns.state.value,
    autofocus: true,
    "phx-blur": "blur",
    "phx-target": assigns.myself
  ]

defp next_button(assigns), do:
  Phoenix.HTML.Tag.tag :input, [
    type: "button",
    value: "Next",
    "phx-click": "next",
    "phx-target": assigns.myself
  ]

Blur handler:

def handle_event("blur", %{"value" => expect_email_input_value}, socket) do
  IO.inspect expect_email_input_value, label: "blur"  # <-- blur: "Next"
  {:noreply, socket}
end

How does the button value end up in my email input field blur handler ?

First Post!

i-n-g-m-a-r

i-n-g-m-a-r

Update, it’s not the blur, it’s very weird though.
Not sure whether the problem exists between my computer and chair.
I have stripped down my component to a working example, see below.

Result is: click, click, boom.
After the third click, as soon as render_error/1 returns a list item, the value of the email input is set to “Next”.
After the fourth click, the list item has been removed and the value is “” again.
The value setting in the state is always “”.

Console output:

"initialized: `%EmailInput{foobar: 0, value: \"\"}`"
"email_input: `%EmailInput{foobar: 0, value: \"\"}`"
"next clicked: `%EmailInput{foobar: 1, value: \"\"}`"
"email_input: `%EmailInput{foobar: 1, value: \"\"}`"
"next clicked: `%EmailInput{foobar: 2, value: \"\"}`"
"email_input: `%EmailInput{foobar: 2, value: \"\"}`"
"next clicked: `%EmailInput{foobar: 3, value: \"\"}`"
"Email input value is set to \"Next\": `%EmailInput{foobar: 3, value: \"\"}`"
"email_input: `%EmailInput{foobar: 3, value: \"\"}`"
"next clicked: `%EmailInput{foobar: 4, value: \"\"}`"
"email_input: `%EmailInput{foobar: 4, value: \"\"}`"
"next clicked: `%EmailInput{foobar: 5, value: \"\"}`"
"email_input: `%EmailInput{foobar: 5, value: \"\"}`"

This is the component:

defmodule EmailInput do
  use Phoenix.LiveComponent

  defstruct [:value, :foobar]

  def render(assigns) do
    ~L"""
      <div id="<%= assigns.id %>">
        <ul>
          <%= render_error(assigns) %>
          <li><%= email_input(assigns) %></li>
          <li><%= next_button(assigns) %></li>
        </ul>
      </div>
    """
  end

  def update(%{id: id, email: email} = _assigns, socket) do
    assigns = [
      id: id,
      state: %__MODULE__{value: email, foobar: 0}
    ]
    socket = assign(socket, assigns)
    IO.inspect "initialized: `#{inspect(socket.assigns.state)}`"
    {:ok, socket}
  end

  def handle_event("next", %{"value" => "Next"}, socket) do
    state  = socket.assigns.state
    foobar = state.foobar + 1
    socket = assign(socket, state: %{state | foobar: foobar})
    IO.inspect "next clicked: `#{inspect(socket.assigns.state)}`"
    {:noreply, socket}
  end

  ## private

  defp render_error(%{state: %{foobar: foobar}} = assigns) when foobar === 3 do
    # boom!
    IO.inspect "Email input value is set to \"Next\": `#{inspect(assigns.state)}`"
    Phoenix.HTML.Tag.content_tag :li, "Invalid"
  end

  defp render_error(_), do: []

  defp email_input(assigns) do
    IO.inspect "email_input: `#{inspect(assigns.state)}`"
    Phoenix.HTML.Tag.tag :input, [
      type: "email",
      name: "email",
      value: assigns.state.value
    ]
  end

  defp next_button(assigns), do:
    Phoenix.HTML.Tag.tag :input, [
      type: "button",
      value: "Next",
      "phx-click": "next",
      "phx-target": assigns.myself
    ]

end

Where Next?

Popular in Questions Top

nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127089 1222
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement