Come gestire float e separatori decimali con il numero del tipo di input html5


128

Sto costruendo un'app Web che è principalmente per i browser mobili. Sto usando campi di input con tipo di numero, quindi (la maggior parte) i browser mobili invocano solo la tastiera numerica per una migliore esperienza utente. Questa app Web viene utilizzata principalmente nelle regioni in cui il separatore decimale è virgola, non punto, quindi ho bisogno di gestire entrambi i separatori decimali.

Come coprire tutto questo casino con punto e virgola?

Le mie scoperte:

Chrome desktop

  • Tipo di input = numero
  • L'utente inserisce "4,55" nel campo di inserimento
  • $("#my_input").val(); restituisce "455"
  • Non riesco a ottenere il valore corretto dall'input

Firefox desktop

  • Tipo di input = numero
  • L'utente inserisce "4,55" nel campo di inserimento
  • $("#my_input").val(); restituisce "4,55"
  • Va bene, posso sostituire la virgola con punto e ottenere il float corretto

Browser Android

  • Tipo di input = numero
  • L'utente inserisce "4,55" nel campo di inserimento
  • Quando l'ingresso perde lo stato attivo, il valore viene troncato a "4"
  • Confuso per l'utente

Windows Phone 8

  • Tipo di input = numero
  • L'utente inserisce "4,55" nel campo di inserimento
  • $("#my_input").val(); restituisce "4,55"
  • Va bene, posso sostituire la virgola con punto e ottenere il float corretto

Quali sono le "migliori pratiche" in questo tipo di situazioni in cui l'utente potrebbe usare la virgola o il punto come separatore decimale e voglio mantenere il tipo di input HTML come numero, per fornire una migliore esperienza utente?

Posso convertire la virgola in punto "al volo", vincolando eventi chiave, funziona con input numerici?

MODIFICARE

Currenlty Non ho alcuna soluzione, come ottenere il valore float (come stringa o numero) dall'input il cui tipo è impostato su numero. Se l'utente finale immette "4,55", Chrome restituisce sempre "455", Firefox restituisce "4,55", il che va bene.

Inoltre è abbastanza fastidioso che in Android (emulatore 4.2 testato), quando inserisco "4,55" per inserire il campo e cambio lo stato attivo da qualche altra parte, il numero inserito viene troncato a "4".


La mia ipotesi è che la causa principale di alcuni dei tuoi problemi è che i browser sono impostati su una locale statunitense che utilizza il punto come separatore decimale. Sembra che Chrome e Android si stiano confondendo in questo modo in diversi modi: Chrome tratta la virgola come un separatore di cifre, quindi converte l'input in un numero, quindi lo converte di nuovo in una stringa .val()e Android fa qualcosa di strano. Puoi verificare se si comportano allo stesso modo quando imposti la lingua del sistema su qualcosa di appropriato?
millimoose

1
Nvm ha pubblicato questo come risposta
kjetilh


La situazione è persino peggiore di quanto immagini: ottieni un punto decimale o una virgola sul tastierino numerico WP a seconda della lingua su cui hai scelto la tastiera su cui lavorare. Inoltre non c'è modo di scoprire quale fosse la locale di input (non necessariamente la lingua preferita del browser) ... Quindi il meglio che potrei inventare (e ciò che è abbastanza buono per me) è: var number = $(...).get(0).valueAsNumber; if (isNaN(number)) number = parseFloat($(...).val().replace(',', '.'); Ma quella soluzione funziona solo se il il numero inserito contiene solo 1 virgola e nessun punto extra ...
bert bruynooghe

Risposte:


107

Penso che ciò che manca nelle risposte sopra sia la necessità di specificare un valore diverso per l' stepattributo, che ha un valore predefinito di 1. Se si desidera che l'algoritmo di convalida dell'input consenta valori in virgola mobile, specificare un passaggio di conseguenza.

Ad esempio, volevo importi in dollari, quindi ho specificato un passaggio come questo:

 <input type="number" name="price"
           pattern="[0-9]+([\.,][0-9]+)?" step="0.01"
            title="This should be a number with up to 2 decimal places.">

Non c'è niente di sbagliato nell'utilizzo di jQuery per recuperare il valore, ma sarà utile utilizzare direttamente l'API DOM per ottenere la validity.validproprietà degli elementi .

Ho avuto un problema simile con il punto decimale, ma il motivo per cui ho capito che c'era un problema era a causa dello stile che Twitter Bootstrap aggiunge a un input numerico con un valore non valido.

Ecco un violino che dimostra che l'aggiunta dell'attributo lo stepfa funzionare e che verifica anche se il valore corrente è valido:

TL; DR: impostare astep imposta attributo a su un valore in virgola mobile, perché per impostazione predefinita è 1.

NOTA : la virgola non è valida per me, ma sospetto che se imposto le impostazioni della lingua / regione del SO su un punto che utilizza una virgola come separatore decimale, funzionerebbe. * nota in nota *: non era il caso delle impostazioni di lingua / tastiera del sistema operativo * Tedesco * in Ubuntu / Gnome 14.04.


8
Se si desidera consentire arbitrariamente molte cifre decimali, specificare l' stepattributo come "any"anziché ad esempio, "0.01"come mostrato qui. Guarda questa versione ottimizzata del violino di Nathciketa per una demo.
Mark Amery,

4
Ho anche riscontrato problemi con virgole non convalidanti, anche se inserivo "1.234,56" in <input type="number" step="any">. Non sono stato in grado di trovare un modo per disattivare la convalida HTML5. Posso disattivare o personalizzare il messaggio di errore, ma recuperare il valore dall'input è sempre un crapshoot. Qualche idea?
Nick G.

5
This attribute applies when the value of the type attribute is text, search, tel, url, email, or password, otherwise it is ignored.Quindi lo schema è inutile contype="number"
Michael Laffargue,

come ha detto michael, ti preghiamo di cambiare typein text, altrimenti la tua risposta non ha senso.
phil294,

23

Secondo w3.org l' attributo value dell'input numerico è definito come un numero a virgola mobile . La sintassi del numero in virgola mobile sembra accettare solo punti come separatori decimali.

Di seguito ho elencato alcune opzioni che potrebbero esserti utili:

1. Utilizzo dell'attributo modello

Con l' attributo pattern è possibile specificare il formato consentito con un'espressione regolare in modo compatibile HTML5. Qui puoi specificare che il carattere virgola è consentito e un utile messaggio di feedback se il modello fallisce.

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" name="my-num"
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>

Nota: il supporto per più browser varia molto. Può essere completo, parziale o inesistente.

2. Convalida JavaScript

Potresti provare a associare un semplice callback ad esempio all'evento onchange (e / o blur ) che sostituisce la virgola o convalida tutti insieme.

3. Disabilitare la convalida del browser ##

In terzo luogo, potresti provare a utilizzare l' attributo formnovalidate sugli input numerici con l'intenzione di disabilitare tutti insieme la convalida del browser per quel campo.

<input type="number" formnovalidate />

4. Combinazione ..?

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" 
           name="my-num" formnovalidate
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>

2
input.valueAsNumber - Nessun aiuto in quanto funziona solo con punti come separatore decimale e nel mio caso l'utilizzatore potrebbe usare punto o virgola. Tag del modulo novalidate - Non ho riscontrato alcun effetto su questo.
Devha,

Sfortunatamente sto esaurendo le idee, quindi non sono sicuro che tu sia in grado di far funzionare questo browser con una soluzione alternativa. Ho aggiornato la mia risposta per includere l' attributo modello Ho anche scoperto che è possibile utilizzare l' attributo formnovalidate direttamente nei campi di input. So che non ti piacerà, ma se tutto fallisce e allora hai assolutamente bisogno di virgole input = "text" potrebbe essere l'unico modo ..
kjetilh

Sembra che il numero del tipo di input generi più problemi di quanti effettivamente migliorino l'esperienza dell'utente. Nel dispositivo mobile sarebbe bello se posso aprire all'utente solo la tastiera numerica se voglio che inseriscano solo numeri. Comunque devo ripensarci ancora una volta ...
Devha,

Poiché dobbiamo anche supportare l'utilizzo di punti e virgola come separatore decimale, prevediamo di utilizzare il modello per la convalida sul desktop in combinazione con type = "testo". Quindi aggiungeremo il rilevamento delle funzionalità per il rilevamento di dispositivi mobili e utilizzeremo type = "number" quando applicabile.
timore re

9

Se utilizzare la virgola o il punto per il separatore decimale dipende interamente dal browser. Il browser prende la decisione in base alle impostazioni locali del sistema operativo o del browser, oppure alcuni browser prendono suggerimenti dal sito Web. Ho creato un grafico di confronto dei browser che mostra come diversi browser supportano la gestione di diversi metodi di localizzazione. Safari è l'unico browser in grado di gestire in modo intercambiabile virgole e punti.

Fondamentalmente, tu come autore web non puoi davvero controllarlo. Alcune soluzioni alternative comportano l'utilizzo di due campi di input con numeri interi. Ciò consente a ogni utente di inserire i dati come previsto. Non è particolarmente sexy, ma funzionerà in ogni caso per tutti gli utenti.


7

Usa valueAsNumberinvece di .val().

input. valueAsNumber [= value]

Restituisce un numero che rappresenta il valore del controllo modulo, se applicabile; in caso contrario, restituisce null.
Può essere impostato per modificare il valore.
Genera un'eccezione INVALID_STATE_ERR se il controllo non è né basato su data o ora né numerico.


2
Il problema è che vuole supportare la virgola come separatore decimale e usando type = "number" sull'input si ottiene sempre un numero non valido quando si scrive la virgola.
timore re

Sembra non funzionare in modo coerente su Windows Phone; ritorna sempre NaN.
Bert Bruynooghe,

@bertbruynooghe, che cosa stai assegnando come valore?
Mike Samuel,

Non sembra funzionare, né con '9', '9,1', '9.1'. Il telefono è configurato come US, layout tastiera testati en-US, nl-BE.
Bert Bruynooghe,

4

utilizza un tipo di testo ma forza l'aspetto della tastiera numerica

<input value="12,4" type="text" inputmode="numeric" pattern="[-+]?[0-9]*[.,]?[0-9]+">

il tag inputmode è la soluzione


Ma non è compatibile con tutti i browser, solo con le ultime versioni di iOS Safari, Chrome, Chromium, Opera ... caniuse.com/#feat=input-inputmode :(
pgarciacamou

Inoltre, questa tastiera numerica non è disponibile sui dispositivi mobili.
WoIIe

3

Non ho trovato una soluzione perfetta ma il meglio che potevo fare era usare type = "tel" e disabilitare la validazione html5 (formnovalidate):

<input name="txtTest" type="tel" value="1,200.00" formnovalidate="formnovalidate" />

Se l'utente inserisce una virgola, verrà emesso con la virgola in ogni browser moderno che ho provato (ultimo FF, IE, edge, opera, chrome, safari desktop, android chrome).

Il problema principale è:

  • Gli utenti mobili vedranno la tastiera del loro telefono che potrebbe essere diversa dalla tastiera numerica.
  • Ancora peggio, la tastiera del telefono potrebbe non avere nemmeno un tasto per una virgola.

Per il mio caso d'uso ho dovuto solo:

  • Visualizza il valore iniziale con una virgola (firefox lo elimina per type = number)
  • Convalida html5 non riuscita (se è presente una virgola)
  • Chiedi al campo di leggere esattamente come input (con una possibile virgola)

Se hai un requisito simile, questo dovrebbe funzionare per te.

Nota: il supporto dell'attributo pattern non mi è piaciuto. Il formnovalidate sembra funzionare molto meglio.


1

Quando lo chiami $("#my_input").val();ritorna come variabile stringa. Quindi usa parseFloate parseIntper convertire. Quando si utilizza parseFloatil desktop o il telefono ITSELF comprende il significato di variabile.

E in più puoi convertire un float in stringa usando toFixedquale ha un argomento il conteggio delle cifre come di seguito:

var i = 0.011;
var ss = i.toFixed(2); //It returns 0.01

Non funziona. Prova parseFloat ("1,5") in IE11. Restituzioni 1. La lingua è il tedesco sia per OS che per IE.
T3rm1,

1

Apparentemente i browser hanno ancora problemi (anche se Chrome e Firefox Nightly vanno bene). Ho un approccio caotico per le persone che devono davvero usare un campo numerico (forse a causa delle piccole frecce che i campi di testo non hanno).

La mia soluzione

Ho aggiunto un keyupgestore eventi all'input del modulo e tracciato lo stato e impostato il valore una volta tornato valido.

Snippet JS puro JSFIDDLE

Snippet angolare 9


0

La mia raccomandazione? Non usare affatto jQuery. Ho avuto il tuo stesso problema. Ho scoperto che $('#my_input').val()restituiscono sempre qualche risultato strano.

Prova a usare document.getElementById('my_input').valueAsNumberinvece di $("#my_input").val();e poi, usa Number(your_value_retrieved)per provare a creare un numero. Se il valore è NaN, sai sicuramente che non è un numero.

Una cosa da aggiungere è quando scrivi un numero sull'input, l'input accetterà effettivamente quasi tutti i caratteri (posso scrivere il simbolo dell'euro, un dollaro e tutti gli altri caratteri speciali), quindi è meglio recuperare il valore usando .valueAsNumber invece di usare jQuery.

Oh, e BTW, che consente ai tuoi utenti di aggiungere internazionalizzazione (es .: supporto virgole invece di punti per creare numeri decimali). Lascia che l' Number()oggetto crei qualcosa per te e sarà decimale, per così dire.


Il problema non è causato da jQuery e trovo che valueAsNumbernon funzioni in modo coerente con i browser.
Bert Bruynooghe,

0

Sembra che ti piacerebbe usare toLocaleString () sui tuoi input numerici.

Vedi https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString per il suo utilizzo.

La localizzazione di numeri in JS è anche coperta in Internazionalizzazione (formattazione numerica "num.toLocaleString ()") non funzionante per Chrome


2
È consuetudine fornire ulteriori spiegazioni della soluzione anche se la risposta è interamente coperta da contenuti collegati.
IvanH,

Questo approccio sembra essere migliore rispetto agli altri se il server back-end sta determinando la locale anziché il browser stesso. Sfortunatamente, toLocaleStringnon è affidabile su tutte le piattaforme.
Bert Bruynooghe,

Il supporto multipiattaforma mi sembra abbastanza ampio nel 2015, ad esempio Mozillas Devnet . Tuttavia, se ancora ti preoccupa, trova le possibili soluzioni qui.
Stackasec,

Mozillas Devnet non mostra quasi alcuna compatibilità per i browser mobili, ed è proprio lì che il campo di testo numerico può offrire la maggior parte dei vantaggi. (Vedi domanda originale.)
bert bruynooghe

... e sono state mostrate e citate alternative più che sufficienti. Divertiti.
Stackasec,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.