Permitir 2 casas decimais em <input type = "number">

221

Eu tenho um <input type="number">e quero restringir a entrada dos usuários apenas para números ou números com decimais com até 2 casas decimais.

Basicamente, estou pedindo uma entrada de preço.

Eu queria evitar fazer regex. Existe uma forma de fazer isso?

<input type="number" required name="price" min="0" value="0" step="any">
nubteens
fonte
2
type = "number" não tem amplo suporte ao navegador. É melhor usar apenas uma caixa de texto com algum javascript para garantir que você obtenha a entrada desejada.
www139
6
Sim, mas as entradas retornam de type="text"qualquer maneira, então o que isso importa?
Ultimater
Possível duplicata de Existe um tipo de entrada flutuante no HTML5?
OhadR 02/09/19
/^\d+\.\d{2,2}$/ trabalhou para que eu exigisse 0,00
ZStoneDPM 30/10/1919

Respostas:

334

Em vez de step="any", que permite qualquer número de casas decimais, use step=".01", que permite até duas casas decimais.

Mais detalhes na especificação: https://www.w3.org/TR/html/sec-forms.html#the-step-attribute

Michael Benjamin
fonte
38
Esta não é a resposta correta. A etapa governa apenas o que acontece quando você clica ou pressiona e não restringe nada.
Ini
1
@ Michael_B, independentemente do que a especificação espera, isso é bastante trivial para testar: jsfiddle.net/9hvm0b5u ainda permite que mais de 2 casas decimais sejam inseridas. As etapas controlam apenas o movimento dos botões +/-. (Chrome)
Nathan
3
@ Michael_B, o usuário não é impedido de digitar um número, como 500.12345em qualquer uma das entradas, talvez nosso entendimento dos requisitos seja diferente.
23418 Nathan
3
Deve-se notar que, embora o usuário possa digitar qualquer número de dígitos após a casa decimal, a maioria dos navegadores não permitirá o envio do formulário com um valor inválido e os seletores CSS :valide :invalidsão aplicados conforme o esperado.
Andrew Dinmore 13/06/19
1
@ Nathan, também é trivial testar a validação do navegador. Tente enviar um valor com mais de duas casas decimais: jsfiddle.net/4yesgn7b
imclean
43

Se alguém estiver procurando por uma regex que permita apenas números com 2 casas decimais opcionais

^\d*(\.\d{0,2})?$

Por exemplo, eu achei a solução abaixo bastante confiável

HTML:

<input name="my_field" pattern="^\d*(\.\d{0,2})?$" />

JS / JQuery:

$(document).on('keydown', 'input[pattern]', function(e){
  var input = $(this);
  var oldVal = input.val();
  var regex = new RegExp(input.attr('pattern'), 'g');

  setTimeout(function(){
    var newVal = input.val();
    if(!regex.test(newVal)){
      input.val(oldVal); 
    }
  }, 0);
});
Weston Ganger
fonte
2
Qual é o objetivo de ter o setTimeout ()?
Derek #
2
@Derek. Suponho que seja para que o regex.test não bloqueie o DOM. Lookup isto: developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
christo8989
2
@ Derek Só posso assumir que setTimeout()é esperar o keydownevento ser concluído antes de definir o newVal(caso contrário, será o mesmo que o oldVal). No entanto, com um tempo limite de 0, é inútil e não funciona, pois os dois valores geralmente são os mesmos (no Firefox). Se você defini-lo como 1, por exemplo, funciona bem.
alstr
Então, você reverteu minha edição em duas postagens diferentes com o motivo "a edição não aprovada diminui a qualidade da formatação da resposta". Você pode explicar como a minha edição não foi aprovada e como exatamente isso prejudica a qualidade da resposta? (IMO, ele melhora, pois as pessoas podem executar o código diretamente da postagem e não precisam acessar o JSFiddle).
bip duplo
21

Por moeda, sugiro:

<div><label>Amount $
    <input type="number" placeholder="0.00" required name="price" min="0" value="0" step="0.01" title="Currency" pattern="^\d+(?:\.\d{1,2})?$" onblur="
this.parentNode.parentNode.style.backgroundColor=/^\d+(?:\.\d{1,2})?$/.test(this.value)?'inherit':'red'
"></label></div>

Consulte http://jsfiddle.net/vx3axsk5/1/

As propriedades "etapa", "min" e "padrão" do HTML5 serão validadas quando o formulário for enviado, não ativadas. Você não precisa do stepse tiver um patterne não precisa do patternse tiver um step. Então você pode voltar ao step="any"meu código, pois o padrão o validará de qualquer maneira.

Se você deseja validar o onblur, acredito que fornecer uma dica visual ao usuário também é útil, como colorir o fundo em vermelho. Se o navegador do usuário não suportar, type="number"ele fará o fallback para type="text". Se o navegador do usuário não suportar a validação de padrão HTML5, meu snippet JavaScript não impede o envio do formulário, mas fornece uma dica visual. Portanto, para pessoas com pouco suporte ao HTML5 e para pessoas que tentam invadir o banco de dados com o JavaScript desativado ou forjar solicitações HTTP, é necessário validar o servidor novamente de qualquer maneira. O ponto com a validação no front-end é para uma melhor experiência do usuário. Desde que a maioria dos usuários tenha uma boa experiência, não há problema em confiar nos recursos HTML5, desde que o código ainda funcione e você possa validar no back-end.

Ultimater
fonte
2
De acordo com o MDN , patternnão funciona para input type=number:<input type="number"> elements do not support use of the pattern attribute for making entered values conform to a specific regex pattern. The rationale for this is that number inputs can't contain anything except numbers, and you can constrain the minimum and maximum number of valid digits using the min and max attributes, as explained above.
izogfif 15/03
@izogfif Boa nota. Observe também que, na verdade, observei que você não precisa dos dois e forneceu três maneiras: Etapa, padrão e onblur. Meu raciocínio na época era se um navegador se engasga com um por algum motivo, ele tem o outro. Provavelmente, é seguro confiar na etapa atual para validação de front-end.
Ultimater
16

Etapa 1: Conecte sua caixa de entrada de número HTML a um evento onchange

myHTMLNumberInput.onchange = setTwoNumberDecimal;

ou no código HTML

<input type="number" onchange="setTwoNumberDecimal" min="0" max="10" step="0.25" value="0.00" />

Etapa 2: escreva o setTwoDecimalPlacemétodo

function setTwoNumberDecimal(event) {
    this.value = parseFloat(this.value).toFixed(2);
}

Você pode alterar o número de casas decimais variando o valor passado para o toFixed()método Veja os documentos MDN .

toFixed(2); // 2 decimal places
toFixed(4); // 4 decimal places
toFixed(0); // integer
Sachin Sudhakar Sonawane
fonte
3
parseFloat (parseFloat (this.value) .toFixed (2)); Se você deseja um tipo decimal ou numérico, pode agrupar tudo em parseFloat (), como padrão, o método toFixed () retorna string.
SpaceDev
6

Eu descobri que usar o jQuery era minha melhor solução.

$( "#my_number_field" ).blur(function() {
    this.value = parseFloat(this.value).toFixed(2);
});
SamohtVII
fonte
6

Tente isso para permitir apenas 2 decimais no tipo de entrada

<input type="number" step="0.01" class="form-control"  />

Ou Use o jQuery, conforme sugerido por @SamohtVII

$( "#ELEMENTID" ).blur(function() {
    this.value = parseFloat(this.value).toFixed(2);
});
Nilesh Gajare
fonte
21
Isso não limita decimais para 2 lugares no Chrome 57
mintedsky
1
Isso não está correto. A etapa governa apenas o que acontece quando você clica ou pressiona e não restringe nada.
Ini
A etapa também impede que números como 1.000 sejam inseridos.
Zapnologica 23/10
-2

Use este código

<input type="number" step="0.01" name="amount" placeholder="0.00">

Por padrão, o valor da etapa para os elementos de entrada HTML5 é step = "1".

Obaidul Haque
fonte
-4

apenas escreva

<input type="number" step="0.1" lang="nb">

lang = 'nb "permite escrever seus números decimais com vírgula ou ponto

ILLUSTRAY KING
fonte
"lang = 'nb' permite que você escreva seus números decimais com vírgula ou ponto" Não posso falar por mais nada, mas isso não funciona no Chrome para mim.
Andrew Dinmore 13/06/19
-9

Na entrada:

step="any"
class="two-decimals"

No script:

$(".two-decimals").change(function(){
  this.value = parseFloat(this.value).toFixed(2);
});
xemasiv
fonte
5
Evite usar insultos em sua postagem. E lembre-se de ser gentil #
James