JavaScript
vue.js

Vue.jsのv-ifで出現するフォームにオートフォーカスする方法

Vue.jsのTodoアプリのサンプルを参考にTodoアプリを作成した際に知った、ダブルクリック後に出現するフォームにオートフォーカスする方法についてのメモ。

実際にelectron-vueで作成したTodoアプリは https://github.com/x-color/todo-app に置いてある。

どうなるか

before

ダブルクリック後にフォームが出現しているのだが、オートフォーカスしていない。

todos-1.gif

after

ダブルクリック後にフォームが出現し、オートフォーカスしている。

todos-2.gif

何をしているのか

Todoを表示する部分。ダブルクリック時にeditTodo()を実行する。

<label @dblclick="editTodo(todo)">{{ todo.title }}</label>

入力フォーム部分。v-ifで描画するかを制御している。

<input v-if="todo.isEditing" id="edit-todo" v-model="todo.title" type="text">

Todoがダブルクリックされた場合に実行される関数。入力フォーム部分の描画条件をtrueにして、自動で入力フォームにフォーカスしている。

editTodo(todo) {
  todo.isEditing = true;
  this.$nextTick(() => document.getElementById('edit-todo').focus());  
}

簡単な解説

v-ifで描画を制御している場合、条件が真になった直後に、

document.getElementById('id').focus();

このコードを実行してもフォーカスしない。これは、条件が真になった直後にDOMが更新されているとは限らないため。

なので、DOMの更新を待った後に実行するために、以下のようにnextTick()を用いて呼び出す必要がある。

nextTick(() => document.getElementById('id').focus());  

備考

バージョンや実行環境によって、nextTick()の挙動が変わるので注意。

Vue.nextTick(() => document.getElementById('id').focus());

// Promiseがサポートされている実行環境かつ、Vue.js 2.1.0以上
Vue.nextTick().then(() => document.getElementById('id').focus());

詳しくは https://jp.vuejs.org/v2/api/index.html#Vue-nextTick を参照