Input text: accetta solo numeri e non può essere vuoto.

  • Creatore Discussione Creatore Discussione otto9due
  • Data di inizio Data di inizio

otto9due

Utente Attivo
22 Feb 2014
591
25
28
Buonasera, come da titolo ho la necessità di fare in modo che un campo di testo accetti solamente numeri e che non ci sia modo per inserire altro, neanche il vuoto, che in caso dev'esere sostituito dallo 0.

Ho fatto questo ma funziona a fasi alterne. Non capisco ancora come alcune volte riesco a scriverci testo ed altre no.

JavaScript:
let el = document.querySelectorAll('[id^="prod-quant-"]');
el.forEach(item => {
    item.addEventListener('input', event => {
        if (item.value.length > 0) {
            item.value = parseInt(item.value.replace(/[^0-9]/g, ''), 10); // parseInt per trasformare numeri tipo 01 -in-> 1
            item.dataset.quant = parseInt(item.value.replace(/[^0-9]/g, ''), 10);
        } else {
            item.value = 0;
            item.dataset.quant = 0;
        }
    });
});
Qualcuno ha qualche idea su come posso perfezionarlo per evitare il problemi?
 
Salve, non mi è molto chiaro il problema che descrivi, cioè "alcune volte riesco a scriverci testo ed altre no".

Da alcune semplici prove che ho fatto, l'unico problema è il fatto che mi restituisca NaN se il campo era vuoto e inserisco qualcosa che non siano numeri. Questo è dovuto al parseInt.

Ad ogni modo, io la imposterei in questa maniera:
JavaScript:
let el = document.querySelectorAll('[id^="prod-quant-"]');
el.forEach(item => {
    item.addEventListener('input', function(){
        this.value = this.dataset.quant = Math.max(0, this.value.replace(/[^\d]/g, ''));
    });
});
Vedi se può andarti bene :)
 
L'ho appena provato velocemente e sembra essere perfetto. Appena rientro avrò modo di testarlo nel progetto e ti dirò meglio per ora cmq Funziona alla grande! Ottima soluzione. Grazie
 
Funziona. Ne approfitto però perchè ho comunque un problema. Il fatto è che questo form si trova all'interno di una tabella dinamica che richiama altri dati in asincrono. Sui nuovi dati ovviamente non funziona. Ho provato a racchiuderla in una funzione e richiamarla al caricamento dei nuovi dati ma non va. Grazie in anticipo per la pazienza.
 
Ho provato a racchiuderla in una funzione e richiamarla al caricamento dei nuovi dati ma non va
Sì, un sistema può essere questo. Bisogna capire come lo hai impostato esattamente, e se quei campi siano selezionabili attraverso quella specifica query ('[id^="prod-quant-"]'). Attenzione però al fatto che richiamando lo stesso script, se non c'è alcun controllo dei campi già funzionanti, otterrai una applicazione multipla dello stesso listener su tali campi. Sarebbe meglio evitarlo.

Ci sono comunque altre tecniche per risolvere, ad esempio ciò che viene definito "event delegation".

Questo è possibile attuarlo con vanilla javascript impostando lo script in modo opportuno. Se però utilizzi jquery, questo sistema lo puoi ottenere in modo semplice con il metodo on().

Quindi, domanda, usi per caso jquery?
 
No, non uso jquery, solo javascript. Gli altri campi hanno tutti questa specifica query ('[id^="prod-quant-"]'). Puoi darmi qualche informazione in più, grazie.
 
Ok, quindi il metodo che hai applicato dovrebbe comunque funzionare, cioè eseguire quello script (che hai posto nella funzione) dopo che gli elementi sono caricati e disponibili sulla pagina.

Se non ti funziona bisogna capire dove sta il problema, ma senza vedere la pagina in esecuzione non posso capirlo. Eventualmente posta il link della pagina in questione se puoi.

L'altra soluzione è la delegazione dell'evento. In sostanza si tratta di applicare il listener ad un elemento ascendente, di cui si ha certezza che resti disponibile sulla pagina. Quindi usare la proprietà "target" dell'oggetto event, per recuperare il primo elemento, che si trova sotto il puntatore, su cui sta avvenendo l'evento. Questo elemento potrebbe quindi essere creato dinamicamente e non essere presente al momento dell'applicazione del listener, ma sarà possibile selezionarlo attraverso la proprietà "target" appena avviene l'evento sull'elemento (ascendente) delegato.

Puoi fare qualche ricerca del tipo "javascript event delegation".
Qui un riferimento tra vari, che spiega come applicarlo: Event delegation

Fai sapere se serve ulteriore aiuto.
 
Mi sembra di aver risolto così. Grazie per il tuo tempo e tuoi preziosi suggerimenti.
JavaScript:
document.addEventListener('input', event => {
    if (event.target.id.includes ('prod-quant-')) {
     event.target.value = event.target.dataset.quant = Math.max(0, event.target.value.replace(/[^\d]/g, ''));
    }
});
Ho legato l'evento al documento. Se esiste una forma più elegante o più precisa, ad esempio verificare se l'id inizia con ... sarei curioso di conoscerla, non ho trovato molto online.
 
Bene, giusto un piccolo accorgimento per essere pignoli: tecnicamente sarebbe meglio delegare l'evento su un elemento (contenitore) più prossimo a quegli input, piuttosto che all'intero "document", sempre se hai certezza che tale elemento resti disponibile sulla pagina.

In questo modo si andrebbe a limitare il più possibile l'esecuzione di quello specifico listener, escludendo a priori gli elementi che non ci interessa tenere in considerazione. Mentre se deleghi su "document", è chiaro che si ottenga ugualmente il risultato voluto, ma la funzione sarebbe eseguita (anche se si interrompe poi sull'if) per qualsiasi elemento dell'intera pagina, che riceve l'evento input.

verificare se l'id inizia con

Per la condizione puoi usare i metodi disponibili per le stringhe, dal momento che il valore dell'id non è altro che una stringa.

Di certo con includes() potresti ottenere dei falsi positivi perché non tiene in considerazione se la porzione di stringa sia presente solo all'inizio della stringa a cui è applicato tale metodo.

Ci sono comunque diverse possibili soluzioni.

Ad esempio puoi usare startsWith():
Codice:
event.target.id.startsWith('prod-quant-')
questo metodo però è una specifica ES6, non va bene se ti serve avere supporto anche per IE11.

In alternativa puoi usare substring():
Codice:
event.target.id.substring(0, 11) === 'prod-quant-'

oppure indexOf():
Codice:
event.target.id.indexOf('prod-quant-') === 0

e altri eventuali.
 
  • Like
Reactions: otto9due

Discussioni simili