Estou criando um aplicativo da Web que é principalmente para navegadores móveis. Como estou usando campos de entrada com o tipo de número, a maioria dos navegadores móveis chama apenas o teclado numérico para melhorar a experiência do usuário. Este aplicativo da Web é usado principalmente em regiões onde o separador decimal é vírgula, não ponto, por isso preciso lidar com os dois separadores decimais.
Como cobrir toda essa bagunça com ponto e vírgula?
Minhas descobertas:
Chrome para computador
- Tipo de entrada = número
- O usuário digita "4,55" no campo de entrada
$("#my_input").val();
retorna "455"- Não consigo obter o valor correto da entrada
Desktop Firefox
- Tipo de entrada = número
- O usuário digita "4,55" no campo de entrada
$("#my_input").val();
retorna "4,55"- Tudo bem, eu posso substituir vírgula por ponto e obter a flutuação correta
Navegador Android
- Tipo de entrada = número
- O usuário digita "4,55" no campo de entrada
- Quando a entrada perde o foco, o valor é truncado para "4"
- Confuso para o usuário
Windows Phone 8
- Tipo de entrada = número
- O usuário digita "4,55" no campo de entrada
$("#my_input").val();
retorna "4,55"- Tudo bem, eu posso substituir vírgula por ponto e obter a flutuação correta
Quais são as "melhores práticas" nesse tipo de situação em que o usuário pode usar vírgula ou ponto como separador decimal e eu quero manter o tipo de entrada html como número, para proporcionar uma melhor experiência ao usuário?
Posso converter vírgula em ponto "on the fly", vinculando eventos importantes, está funcionando com entradas numéricas?
EDITAR
Atualmente, eu não tenho nenhuma solução, como obter valor flutuante (como string ou número) da entrada que tipo está definido como número. Se o usuário final digitar "4,55", o Chrome sempre retornará "455", o Firefox retornará "4,55", o que é bom.
Também é bastante irritante que no Android (emulador 4.2 testado), quando eu digito "4,55" para inserir o campo e mudo o foco para outro lugar, o número digitado seja truncado para "4".
.val()
, e o Android faz algo estranho. Você pode verificar se eles se comportam da mesma maneira quando você define o idioma do sistema para algo apropriado?var number = $(...).get(0).valueAsNumber;
if (isNaN(number)) number = parseFloat($(...).val().replace(',', '.');
Mas essa solução só funciona se o número que tem sido posta em apenas contém uma vírgula e sem pontos extras ...Respostas:
Acho que o que falta nas respostas acima é a necessidade de especificar um valor diferente para o
step
atributo, que tem um valor padrão de1
. Se você deseja que o algoritmo de validação da entrada permita valores de ponto flutuante, especifique uma etapa de acordo.Por exemplo, eu queria quantias em dólares, então especifiquei uma etapa como esta:
Não há nada errado em usar o jQuery para recuperar o valor, mas você achará útil usar a API DOM diretamente para obter a
validity.valid
propriedade dos elementos .Eu tive um problema semelhante com o ponto decimal, mas a razão pela qual percebi que havia um problema era devido ao estilo que o Twitter Bootstrap adiciona a uma entrada de número com um valor inválido.
Aqui está um violino demonstrando que a adição do
step
atributo o faz funcionar e também testando se o valor atual é válido:TL; DR: defina o
step
atributo a como um valor de ponto flutuante, porque o padrão é1
.NOTA : A vírgula não é válida para mim, mas suspeito que, se eu definir as configurações de idioma / região do SO em algum lugar que use uma vírgula como separador decimal, funcionará. * note in note *: esse não foi o caso das configurações de idioma / teclado do SO * alemão * no Ubuntu / Gnome 14.04.
fonte
step
atributo como em"any"
vez de, por exemplo,"0.01"
como mostrado aqui. Veja esta versão aprimorada do violino de nathciketa para uma demonstração.<input type="number" step="any">
. Não consegui encontrar uma maneira de desativar a validação HTML5. Posso desativar ou personalizar a mensagem de erro, mas recuperar o valor da entrada é sempre um dado de craps. Alguma ideia?This attribute applies when the value of the type attribute is text, search, tel, url, email, or password, otherwise it is ignored.
Então, o padrão é inútil comtype="number"
type
paratext
, caso contrário, sua resposta não faz sentido.Segundo o w3.org, o atributo value da entrada numérica é definido como um número de ponto flutuante . A sintaxe do número de ponto flutuante parece aceitar apenas pontos como separadores decimais.
Listei algumas opções abaixo que podem ser úteis para você:
1. Usando o atributo padrão
Com o atributo padrão, você pode especificar o formato permitido com uma expressão regular de forma compatível com HTML5. Aqui você pode especificar que o caractere de vírgula é permitido e uma mensagem de feedback útil se o padrão falhar.
Nota: O suporte entre navegadores varia muito. Pode ser completo, parcial ou inexistente.
2. Validação de JavaScript
Você pode tentar vincular um retorno de chamada simples a, por exemplo, o evento onchange (e / ou blur ) que substituiria a vírgula ou validaria todos juntos.
3. Desative a validação do navegador ##
Em terceiro lugar, você poderia tentar usar o atributo formnovalidate nas entradas numéricas com a intenção de desativar a validação do navegador para esse campo todos juntos.
4. Combinação ..?
fonte
O uso de vírgula ou ponto no separador decimal depende inteiramente do navegador. O navegador toma sua decisão com base na localidade do sistema operacional ou do navegador, ou alguns navegadores recebem dicas do site. Fiz um gráfico de comparação de navegadores mostrando como diferentes navegadores suportam os diferentes métodos de localização. O Safari é o único navegador que manipula vírgulas e períodos de forma intercambiável.
Basicamente, você como autor da Web não pode realmente controlar isso. Algumas soluções alternativas envolvem o uso de dois campos de entrada com números inteiros. Isso permite que cada usuário insira os dados conforme o esperado. Não é particularmente sexy, mas funcionará em todos os casos para todos os usuários.
fonte
Use em
valueAsNumber
vez de.val()
.fonte
NaN
.usa um tipo de texto, mas força a aparência do teclado numérico
a tag inputmode é a solução
fonte
Não encontrei uma solução perfeita, mas o melhor que pude fazer foi usar type = "tel" e desativar a validação html5 (formnovalidate):
Se o usuário colocar uma vírgula, ele será gerado com a vírgula em todos os navegadores modernos que tentei (mais recentes FF, IE, edge, opera, chrome, safari desktop, android chrome).
O principal problema é:
Para o meu caso de uso, eu só precisava:
Se você tiver um requisito semelhante, isso deve funcionar para você.
Nota: Não gostei do suporte do atributo pattern. O formnovalidato parece funcionar muito melhor.
fonte
Quando você chama
$("#my_input").val();
, retorna como variável de string. Então useparseFloat
eparseInt
para converter. Quando você usaparseFloat
sua área de trabalho ou telefone, o ITSELF entende o significado de variável.Além disso, você pode converter um float em string usando o
toFixed
qual possui um argumento a contagem de dígitos conforme abaixo:fonte
Aparentemente, os navegadores ainda têm problemas (embora o Chrome e o Firefox Nightly estejam bem). Eu tenho uma abordagem hacky para as pessoas que realmente precisam usar um campo numérico (talvez por causa das pequenas flechas que os campos de texto não possuem).
Minha solução
Adicionei um
keyup
manipulador de eventos à entrada do formulário e rastreie o estado e defina o valor assim que ele for válido novamente.Snippet JS puro JSFIDDLE
Mostrar snippet de código
Snippet angular 9
Mostrar snippet de código
fonte
Minha recomendação? Não use jQuery. Eu tive o mesmo problema que você. Eu descobri que
$('#my_input').val()
sempre retorna algum resultado estranho.Tente usar em
document.getElementById('my_input').valueAsNumber
vez de$("#my_input").val();
e, em seguida, useNumber(your_value_retrieved)
para tentar criar um número. Se o valor for NaN, você certamente sabe que isso não é um número.Uma coisa a acrescentar é que, quando você escreve um número na entrada, ela realmente aceita quase qualquer caractere (eu posso escrever o sinal do euro, um dólar e todos os outros caracteres especiais); portanto, é melhor recuperar o valor usando
.valueAsNumber
em vez de usar jQuery.Ah, e BTW, isso permite que seus usuários adicionem internacionalização (por exemplo: vírgulas de suporte em vez de pontos para criar números decimais). Apenas deixe o
Number()
objeto criar algo para você e ele será seguro como decimal, por assim dizer.fonte
valueAsNumber
também não está funcionando de maneira consistente nos navegadores.Parece que você gostaria de usar toLocaleString () em suas entradas numéricas.
Consulte https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString para seu uso.
A localização de números em JS também é abordada em Internacionalização (a formatação de números "num.toLocaleString ()") não funciona no chrome
fonte
toLocaleString
não é confiável entre plataformas.