JavaScript: gestire i campi di tipo numerico in modo personalizzato

In JavaScript possiamo gestire i campi di input di tipo numerico con facilità.

Partiamo dalla seguente marcatura.


<form action="" method="post">
    <div class="input-number">
        <input type="number" min="1" max="10" value="1">
        <div class="plus-minus" aria-hidden="true">
            <span class="plus">+</span>
            <span class="minus">-</span>
        </div>
    </div>
</form>

Vogliamo che i nostri controlli personalizzati si sovrappongano a quelli predefiniti per questo tipo di campo. Definiamo quindi i seguenti stili CSS.


.input-number {
    width: 100%;
    position: relative;
}

input[type=number] {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: 10px;
    background: #fff;
    border: 1px solid #ccc;
}

.plus-minus {
    width: 2.6em;
    background: #fff;
    position: absolute;
    top: 6px;
    right: 3px;
    z-index: 1000;
}

.plus-minus span {
    cursor: pointer;
    font-size: 18px;
    font-family: Helvetica, Arial, sans-serif;
    display: inline-block;
    margin: 0 4px;
    font-weight: bold;
}

Ora dobbiamo fare in modo che l'utente non inserisca valori maggiori o minori di quelli stabiliti negli attributi min e max.


const handleChange = inputs => {
    inputs.forEach(input => {
        input.addEventListener('change', () => {
            const min = parseInt(input.getAttribute('min'), 10);
            const max = parseInt(input.getAttribute('max'), 10);

            if(/^\d+$/.test(input.value)) {
                let value = parseInt(input.value, 10);

                if(value < min) {
                    input.value = min;
                }
                if(value > max) {
                    input.value = max;
                }
            }
        });
    });
};

Quindi definiamo i controlli personalizzati che andranno ad incrementare o decrementare il valore del campo. Facciamo in modo che ad ogni modifica venga innescato l'evento change per permettere al codice definito in precedenza di operare.


const handleVariations = elements => {
    elements.forEach(element => {
        const plus = element.querySelector('.plus');
        const minus = element.querySelector('.minus');
        const input = element.previousElementSibling;

        plus.addEventListener('click', () => {
            if(/^\d+$/.test(input.value)) {
                let value = parseInt(input.value, 10);
                input.value = value + 1;
                const event = new Event('change', { bubbles: true });
                input.dispatchEvent(event);
            }
        });

        minus.addEventListener('click', () => {
            if(/^\d+$/.test(input.value)) {
                let value = parseInt(input.value, 10);
                input.value = value - 1;
                const event = new Event('change', { bubbles: true });
                input.dispatchEvent(event);
            }
        });
    });
};

Infine, inizializziamo il nostro codice.


document.addEventListener('DOMContentLoaded', () => {
   handleChange(document.querySelectorAll('input[type="number"]'));
   handleVariations(document.querySelectorAll('.plus-minus'));
});

Demo

JavaScript: number input

Torna su