web-dev-qa-db-fra.com

Vue JS focus entrée suivante sur enter

J'ai 2 entrées et je souhaite passer de la première à la seconde lorsque l'utilisateur appuie sur Entrée. J'ai essayé de mélanger jQuery avec Vue parce que je ne trouve aucune fonction pour se concentrer sur quelque chose dans la documentation Vue:

<input v-on:keyup.enter="$(':focus').next('input').focus()"
    ...>
<input  ...>

Mais en entrant je vois une erreur dans la console:

build.js:11079 [Vue warn]: Property or method "$" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in anonymous component - use the "name" option for better debugging messages.)warn @ build.js:11079has @ build.js:9011keyup @ build.js:15333(anonymous function) @ build.js:10111
build.js:15333 Uncaught TypeError: $ is not a function
11
Ivan Borshchov

Vous pouvez essayer quelque chose comme ceci:

<input v-on:keyup.enter="$event.target.nextElementSibling.focus()" type="text">

Exemple JSfiddle

16
yurzui

À la suite de @zurzui, voici à mon avis une alternative plus propre utilisant le $refs API ( https://vuejs.org/v2/api/#vm-refs ).

En utilisant le $refs API, peut vous permettre de cibler l'élément de manière plus simple sans traverser le DOM.

Exemple: https://jsfiddle.net/xjdujke7/1/

7
Blake Newman
directives: {
    focusNextOnEnter: {
        inserted: function (el,binding,vnode) {
            let length = vnode.Elm.length;
            vnode.Elm[0].focus();
            let index = 0;
            el.addEventListener("keyup",(ev) => {
                if (ev.keyCode === 13 && index<length-1) {
                  index++;
                  vnode.Elm[index].focus();
                }
            });
            for (let i = 0;i<length-1;i++) {
                vnode.Elm[i].onfocus = (function(i) {
                  return function () {
                    index = i;
                  }
                })(i);
            }
        }
    }
}

// utilise le

<el-form v-focusNextOnEnter>
...
</el-form>
2
silang

Après quelques tests, ça marche

new Vue({
    el:'#app',
    methods: {
      nextPlease: function (event) {
        document.getElementById('input2').focus();
      }
    }
});
<script src="https://vuejs.org/js/vue.js"></script>
<div id='app'>
    <input type="text" v-on:keyup.enter="nextPlease">
    <input id="input2" type="text">
</div>
2
Robiseb

Bien que j'aimais la réponse aux directives car elle fonctionnait avec des entrées à l'intérieur d'autres éléments (wrappers de style, etc.), j'ai trouvé que c'était un peu rigide pour les éléments qui vont et viennent, surtout s'ils vont et viennent selon d'autres champs. Il a également fait quelque chose de plus.

Au lieu de cela, j'ai rassemblé les deux directives différentes suivantes. Utilisez-les dans votre HTML selon:

<form v-forcusNextOnEnter v-focusFirstOnLoad>
...
</form>

Définissez-les sur votre Vue objet (ou dans un mixin) avec:

directives: {
        focusFirstOnLoad: {
            inserted(el, binding, vnode) {
                vnode.Elm[0].focus();
            },
        },
        focusNextOnEnter: {
            inserted(el, binding, vnode) {
                el.addEventListener('keyup', (ev) => {
                    let index = [...vnode.Elm.elements].indexOf(ev.target);

                    if (ev.keyCode === 13 && index < vnode.Elm.length - 1) {
                        vnode.Elm[index + 1].focus();
                    }
                });
            },
        },
    },

Lorsqu'une touche Entrée est enfoncée, elle recherche l'index de l'entrée actuelle dans la liste des entrées, vérifie qu'elle peut être augmentée et concentre l'élément suivant.

Différences clés: la longueur et l'index sont calculés au moment du clic, ce qui le rend plus adapté à l'ajout/la suppression de champs; aucun événement supplémentaire n'est nécessaire pour modifier une variable mise en cache.

Inconvénient, cela sera un peu plus lent/plus intensif à exécuter, mais étant donné qu'il est basé sur une interaction avec l'interface utilisateur ...

1
SEoF