0

I'm making a little todo app in AlpineJS and I'm running into a problem of autoselecting a field when a user clicks on a todo. This problem only happens when there are multiple todos.

When the user enters the first todo onto the app, they can then click on the todo to edit it. The field will autoselect as expected. However, when the user adds more than one todo onto the app and wants to edit the n+1 todo, the field will no longer autoselects, but the first todo still autoselects just fine.

Here's my CodePen for your reference.

Here's what my edit functionality looks like:

JS

[...]
edit(todo) {
    todo.editing = !todo.editing
    this.$nextTick(() => {
      document.getElementById(`edit-${todo.id}`).select()
    })
  }
[...]

HTML

[...]
<div
  x-text="todo.item"
  class="todo-item"
  @click="edit(todo)" // <-- point of interest
  x-show="!todo.editing"
  :class="{ 'completed' : todo.completed }"
  >
</div>

<input
  type="text"
  x-show="todo.editing"
  :value="todo.item"
  x-model="todo.item"
  @keydown.enter="edit(todo)"
  @keydown.escape="todo.editing = false"
  @click.away="todo.editing = false"
  class="edit-input"
  :id="`edit-${todo.id}`" // <-- point of interest
/>
[...]

Would anyone have an idea of what might be wrong with my logic? Thank you for the help!

Student22
  • 1,979
  • 5
  • 22
  • 33

1 Answers1

0

It seems using setTimeout(() => { ... }, 1) (timeout of 1ms) works, see the following Codepen modified from yours.

There are known issues in Alpine.js around $nextTick.

I would also recommend using x-ref instead of ids, so your input would look as follows:

<input
  type="text"
  x-show="todo.editing"
  :value="todo.item"
  x-model="todo.item"
  @keydown.enter="edit(todo)"
  @keydown.escape="todo.editing = false"
  @click.away="todo.editing = false"
  class="edit-input"
  :x-ref="`edit-${todo.id}`"
/>

You can then set edit(todo) to be:

  edit(todo) {
    todo.editing = !todo.editing
    setTimeout(() => {
      this.$refs[`edit-${todo.id}`].select()
    }, 1)
  }
Hugo
  • 3,500
  • 1
  • 14
  • 28