J'ai plusieurs champs de saisie et je souhaite les limiter pour n'accepter que des nombres dans Vue.js.
Je souhaite empêcher l'utilisateur de saisir des caractères à l'exception des chiffres de 0 à 9. Je l'ai déjà fait avec succès en faisant ceci (cette solution copie-coller preuve ):

Code dans le modèle Vue.js:

<input type="text" name="priceMax" class="input" @input="correctNumberInput" />

Méthode qui supprime tout sauf les nombres:

correctNumberInput: function(event){   
          event.target.value = event.target.value.replace(/[^0-9]/g, "");
        }

Cela a parfaitement fonctionné dans plusieurs domaines.

Voici le problème: Pour une raison différente, j'ai dû utiliser sur ces champs de saisie. Après avoir ajouté le < cyclev-model, ma méthode ne fonctionne plus. Je suppose que c'est parce que v-model utilise également un événement d'entrée sous le capot. Donc, seul l'ajout de "v-model" l'empêche de fonctionner:

<input type="text" name="priceMax" class="input" @input="correctNumberInput" v-model="priceMax" />

J'ai peu de solutions possibles en tête, mais toutes incluent beaucoup de code répété.

Par exemple, je pourrais ajouter des observateurs pour chaque champ de saisie, mais ce serait beaucoup de code répété (car j'aurais besoin de le faire pour chaque champ de saisie). J'ai 5 champs d'entrée, donc fondamentalement, j'aurais besoin d'écrire 5 observateurs presque identiques. Je voudrais éviter cela si cela est possible ... Par exemple:

watch:{
   number(){
      this.priceMax = this.priceMax.replace(/[^0-9]/g, "");
   }
}

Existe-t-il un moyen de le résoudre et de le rendre aussi simple que ma solution était sans répéter le code ? Ce serait bien d'avoir également une solution qui soit à l'épreuve du copier-coller. Toutes les suggestions sont les bienvenues! Merci d'avance!

0
Vasilije Bursac 26 août 2020 à 00:11

2 réponses

Meilleure réponse

J'ai essayé de tester du code. Voici ce que j'ai ( lien vers l'exemple ):

<template>
  <div>
    <div>
      <input
        type="text"
        name="priceMin"
        class="input"
        v-model="priceMin"
        @input="correctNumberInput"
      >
      <label v-html="priceMin"></label>
    </div>
    <div>
      <input
        type="text"
        name="priceMax"
        class="input"
        v-model="priceMax"
        @input="correctNumberInput"
      >
      <label v-html="priceMax"></label>
    </div>
  </div>
</template>

<script>
export default {
  name: "MyInput",
  data: () => {
    return {
      priceMin: "",
      priceMax: ""
    };
  },
  methods: {
    correctNumberInput: function(event, data) {
      const name = event.target.name;
      let value = String(this[name]).replace(/[^0-9]/g, "");
      if (value) {
        this[name] = parseInt(value, 10);
      } else {
        this[name] = "";
      }
    }
  }
};
</script>

<style scoped>
input {
  border: 1px solid black;
}
</style>

Voici le code:

correctNumberInput: function(event, data) {
  const name = event.target.name;
  let value = String(this[name]).replace(/[^0-9]/g, "");
  if (value) {
    this[name] = parseInt(value, 10);
  } else {
    this[name] = "";
  }
}

J'ai donc utilisé votre fonction, mais je ne change pas le event.target.value, je change le data. J'ai donc besoin de connaître le nom de ces données, c'est pourquoi j'utilise l'attribut name des champs d'entrée (const name = event.target.name;)

Mettre à jour

Si nous avons input type=number, alors il a une valeur étrange (vide) dans le rappel @input. Il semble donc préférable d'utiliser le filtre du clavier (exemple ici):

L'idée principale d'avoir un filtre de clavier:

filterDigitKeys: function(event) {
  const code = window.Event ? event.which : event.keyCode;
  const isSpecial =
    code === 37 ||
    code === 39 ||
    code === 8 ||
    code === 46 ||
    code === 35 ||
    code === 36;
  const isDigit = code >= 48 && code <= 57;
  const isKeypad = code >= 96 && code <= 105;
  if (!isSpecial && !isDigit && !isKeypad) {
    // if not number or special (arrows, delete, home, end)
    event.preventDefault();
    return false;
  }
}

Et attachez-le aux entrées:

<input type="number" min="0" name="numberInput" class="input"
    v-model.number="numberInput" @keydown="filterDigitKeys">

Remarque: si nous ne conservons que le gestionnaire @keydown, nous ne filtrerons pas l'insertion de texte dans nos entrées (mais ctrl + v ne fonctionne de toute façon pas, uniquement à la souris).

1
Anton 26 août 2020 à 20:33

Vous pouvez peut-être essayer ceci:

<input type="number" name="priceMax" class="input" @input="correctNumberInput" v-model.number="priceMax" />

Depuis ce site: cliquez sur.

1
Anton 25 août 2020 à 21:16