Tengo varios campos de entrada y quiero limitarlos para aceptar solo números en Vue.js.
Quiero que el usuario no escriba ningún carácter excepto los dígitos del 0 al 9. Ya lo hice con éxito al hacer esto (esta solución copiar y pegar prueba ):

Código en la plantilla de Vue.js:

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

Método que elimina todo excepto los números:

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

Esto funcionó perfectamente bien en múltiples campos.

Aquí viene el problema: por un motivo diferente, necesitaba usar <”v-model en estos campos de entrada. Después de agregar <”v-model mi método ya no funciona. Supongo que es porque v-model también usa evento de entrada debajo del capó. Entonces, solo agregando "v-model", deja de funcionar:

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

Tengo pocas soluciones posibles en mente, pero todas incluyen mucho código repetido.

Por ejemplo, podría agregar observadores para cada campo de entrada, pero eso sería mucho código repetido (porque tendría que hacerlo para cada campo de entrada). Tengo 5 campos de entrada, así que básicamente necesitaría escribir 5 observadores casi idénticos. Me gustaría evitar eso si eso es posible ... Por ejemplo:

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

¿Hay alguna forma de que pueda resolverlo y hacerlo tan simple como mi solución fue sin repetir código ? Sería bueno tener también una solución que sea a prueba de copiar y pegar. ¡Todas las sugerencias son bienvenidas! ¡Gracias por adelantado!

0
Vasilije Bursac 26 ago. 2020 a las 00:11

2 respuestas

La mejor respuesta

Intenté probar algún código. Aquí lo que tengo (enlace al ejemplo):

<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>

Este es el código:

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] = "";
  }
}

Entonces usé su función, pero no voy a cambiar event.target.value, estoy cambiando data. Entonces necesito saber el nombre de esos datos, por eso uso el atributo name de los campos de entrada (const name = event.target.name;)

Actualizar

Si tenemos input type=number, entonces tiene un valor extraño (vacío) dentro de la devolución de llamada @input. Por lo que parece, es mejor usar el filtro de teclado (ejemplo aquí):

La idea principal de tener un filtro de teclado:

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;
  }
}

Y adjúntelo a las entradas:

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

Nota: si solo mantenemos el controlador @keydown, entonces no filtraremos la inserción de texto en nuestras entradas (pero ctrl + v no funciona de todos modos, solo con el mouse).

1
Anton 26 ago. 2020 a las 20:33

Quizás puedas probar esto:

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

Desde ese sitio: haga clic en.

1
Anton 25 ago. 2020 a las 21:16