svb

svb

Hi!

Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a newline to my input field (which is expected behaviour).

Is there a way to make submit work on pressing the Enter key without messing up the way the form is cleared after submitting?

I’m using below code to make the form work. This form works properly when the type of the input element is the default text type rather than a “textarea”.

    <div class="flex items-center py-2">
      <.form for={@form} phx-submit="save" phx-change="update" phx-target={@myself} >
        <.input type="textarea" field={@form[:content]} placeholder="Start typing..." autocomplete="off"/>
        <.button class="text-black" phx-disable-with="Submit">
          Submit
        </.button>
      </.form>
    </div>

Cheers,
Sil

Showing Posts 1 to 6

codeanpeace

codeanpeace

Welcome!

Here’s three distinct things to consider:

  1. listening for user interaction with a generic JS event listener on the textarea input e.g. on key down for the Enter keycode
  2. handling that event by triggering a phx-submit event on the form e.g. dispatching a “submit” event
  3. attaching the JS event listener/handler to the textarea input of a LiveView form e.g. LiveView client hooks via phx-hook

All together that might look something like:

<input type="textarea" ... phx-hook="TextArea" />
let Hooks = {}
Hooks.TextArea = {
  mounted() {
    this.el.addEventListener("keydown", e => {
      if (event.key == "Enter") {
        event.preventDefault();
        this.el.form.dispatchEvent(
          new Event("submit", {bubbles: true, cancelable: true})
        )
      }
    })
  }
}

let liveSocket = new LiveSocket("/live", Socket, {hooks: Hooks, ...})
theodore

theodore

Hey, I was just working on this today. very frustrating.
My form wasn’t clearing when a user presses enter. Seems related to: https://stackoverflow.com/questions/63649891/reset-form-input-field-after-submit-in-phoenix-liveview

This is my pure Elixir w/ a lil bit of Liveview.JS solution. One caveat, if the user presses “shift + enter”, the form will submit

def mount(socket) do
  {:ok,
   socket
   |> assign(:input_message_form, to_form(%{"message" => ""}))
   |> assign(:user_input_value, "")}
end

def handle_event("submit_message", %{"message" => message}, socket) do
  # Do something with the message
  {:noreply, socket |> assign(:user_input_value, "")}
end

def handle_event("user_input_change", %{"message" => changed_input_value}, socket) do
  {:noreply, socket |> assign(:user_input_value, changed_input_value)}
end

def render(assigns) do
  ~H"""
  <.form
    id="input-message-form"
    for={@input_message_form}
    phx-submit="submit_message"
    phx-target={@myself}>
    
    <.input
    field={@input_message_form[:message]}
    type="textarea"
    phx-keydown={JS.dispatch("submit", to: "#input-message-form")}
    phx-key="Enter"
    phx-change="user_input_change"
    phx-target={@myself}
    value={@user_input_value}
    />
    <button type="submit">Submit</button>
  </.form>
  """
end

svb

svb OP

Thanks for the quick reply!

Works like a charm. I think the way the submit event is triggered from this hooks is a neat solution :slight_smile:

I’ve added a check on the Shift key so that form will not submit on Shift+Enter and instead will add a newline to the textarea:

mounted() {
  this.el.addEventListener("keydown", e => {
    if (e.key == "Enter" && e.shiftKey == false) {
      e.preventDefault();
      this.el.form.dispatchEvent(
        new Event("submit", {bubbles: true, cancelable: true})
      )
    }
  })
}
svb

svb OP

Hi theodore,

I think you don’t need the value={@user_input_value} since you already bind field={@input_message_form[:message]}. If you get rid of the @user_input_value you can use the form itself to update the value. For proper clearing of the form it was necessary to update the form with the phx-change callback function (see How to clear a textbox after submit - #2 by andreaseriksson).

My LiveComponent looks like below, but this should also work for a LiveView:

  def update(assigns, socket) do
    {:ok,
     socket
     |> assign(assigns)
     |> assign_form}
  end

  defp assign_form(socket, content \\ nil) do
    assign(socket, :form, to_form(%{"content" => content}, as: "message"))
  end

  def handle_event("update", %{"message" => %{"content" => content}}, socket) do
    # This function seems to be required for clearing the form after submitting because Phoenix LiveView
    # needs to keep track of the items and can't clean properly otherwise (https://forum.elixirforum.com/t/how-to-clear-a-textbox-after-submit/47002/2)
    {:noreply,
     socket
     |> assign_form(content)}
  end

  def handle_event("save", %{"message" => message_params}, socket) do
    # We don't want to handle messages here. Send them to parent and let parent
    # deal with it.
    send self(), {:new_message, message_params}

    # Set empty form since we propagated the message to parent
    {:noreply,
     socket
     |> assign_form}
  end

  def render(assigns) do
    ~H"""
    <div>
      <.form id="message-form" for={@form} phx-submit="save" phx-change="update" phx-target={@myself}>
        <div class="flex-1 min-w-0">
          <.input
            field={@form[:content]}
            placeholder="Start typing..."
            autocomplete="off"
           />
        </div>
        <.button phx-disable-with="Submit">
          Submit
        </.button>
      </.form>
    </div>
    """
  end

Maybe try making it function properly first with a regular form and then switch to a textarea by using the code suggested by @codeanpeace?

theodore

theodore

Yea that’s what I thought too, but for some reason the field attribute doesn’t populate the value inside the input. I think I’ll also switch to hooks so I can easily have the shift + enter functionality.

axelclark

axelclark

I was running into a similar issue. I ended up pushing an event after creating a new message then clearing the field when I receive the event in the frontent.

in form_component.ex

    case Chats.create_message(message_params) do
      {:ok, _message} ->
        {:noreply,
         socket
         |> push_event("clear-textarea", %{id: "message_content"})
         |> push_patch(to: socket.assigns.patch)}

in app.js

window.addEventListener(`phx:clear-textarea`, (e) => {
  let el = document.getElementById(e.detail.id)
  el.value = ""
})
— All posts loaded —

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews