4
respostas

Máscara

O que fazer para que o preço do livro apareça automaticamente o "ponto"? No caso quando eu digitar 15090 o preço ficar 150.90

4 respostas

Olá Lucas, tudo bem com você?

Poxa, ai você pediu uma coisa complicada! Eu vou te sugerir uma abordagem, mas que terá impacto em 2 partes do código, devem existir algumas soluções elegantes utilizando bibliotecas, mas eu fiz utilizando os recursos básicos da linguagem, ok?

  • Criar uma função para pegar o input do usuário e transformar no formato que deseja

O que eu fiz foi dentro do nosso form.marko adicionar uma tag de script para trabalhar o que o usuário digita:

<--- RESTO DO HTML ---->
            <input type="submit" value="Salvar" />
        </form>
    </body>
    <script>
        const inputValor = document.getElementById("preco");
        let format = new Intl.NumberFormat('pt-BR', { style: 'decimal', currency: 'BRL'})

        inputValor.addEventListener('change', event => {
            let valor = event.target.value;

            if(!isNaN(parseInt(valor)) && valor.split(',').length < 3){
                if(valor.includes(",")) {
                    valor = valor.replace(",", ".");
                }
                inputValor.value = format.format(valor);
            }
        })
    </script>

Aqui poderíamos criar várias funções para separar o que o usuário digita por pontos, mas eu optei por utilizar uma API própria do javascript Intlque pega um valor e transforma em formato numérico de acordo com a localização.

Após isso criei um evento para ouvir quando o usuário termina de digitar, para pegar o valor que ele digitou e verificar se o que ele digitou é um número, caso seja eu faço a formatação, caso não, eu deixo normal

  • Manipular a resposta que chega no servidor

Agora não estaremos mais enviando um número para o nosso servidor e sim uma string no formato monetário, então lá precisamos desconverter para poder salvar no banco de dados

    app.post('/livros', function(req, resp) {

        const preco = req.body.preco.replace(/\./g, "").replace(",", ".");
        const data = {
            ...req.body,
            preco,
        }
        const livroDao = new LivroDao(db);
        livroDao.adiciona(data)
                .then(resp.redirect('/livros'))
                .catch(erro => console.log(erro));
    });

Então agora eu pego o preço que é enviado e tiro todos os pontos e substituo onde poderia ter uma vírgula pelo ponto, após isso eu crio um objeto data que terá todos os atributos do req.body mas eu modifico o valor de preço para ser o nosso novo dado

Dessa maneira teremos agora a nossa aplicação funcionando corretamente, mas faço um adendo:

  • Existem várias biblioteca na internet que fazem essa conversão, poderíamos linkar em nosso html e utilizar alguma função
  • Eu não recomendaria fazer essa mudança agora porque na parte 2 do curso iremos utilizar algumas validações que podem quebrar um pouco com essas mudanças que eu fiz

Mas a ideia é basicamente essa :)

Abraços e Bons Estudos!

Pode mandar soluções mais rebuscadas... Eu já terminei o curso dois, mas ainda assim não havia a solução...

Tava vendo a solução com JQuery, mas ainda assim não consegui implementar, se puder mandar mais alternativas, agradeço.

No aguardo...

Opa Lucas,

Passei os últimos dias procurando algumas alternativas, mas nenhuma que se adaptassem bem ao marco, entretanto achei uma função que consegue o que você queria, mas ainda teremos que utilizar o formato tradicional:

Em nosso form.marko vamos adicionar o seguinte script, ao invés de utilizar a própria API de formatação do javascript vamos utilizar as expressões regulares para formatar da maneira que você quer:

    <script>
        let $input = document.getElementById("preco");
        function formatarValor(){
            let $valor = $input.value;
            $valor += '';
            $valor = parseInt($valor.replace(/[\D]+/g,''));
            if(isNaN($valor)) return;
            $valor += '';
            $valor = $valor.replace(/(\d{2})$/g, ",$1");

            if($valor.length > 6){
                $valor = $valor.replace(/(\d{3}),(\d{2})$/g, ".$1,$2");
            }

            $input.value = $valor;
        }
    </script

E em nosso input:

<input type="text" id="preco" name="preco" value="${data.livro.preco}" placeholder="150.25" onkeyup="formatarValor()" />

Dessa forma quando digitamos:

1 >> 1
15 >> 0,15
150 >> 1,50
1509 >> 15,90
15090 >> 150,90

Mas novamente, como estamos enviado uma string para o nosso servidor precisamos fazer o processo inverso:

    app.post('/livros', function(req, resp) {
        console.log(req.body);

        const preco = req.body.preco.replace(/\./g, '').replace(',', '.');
        const data = {
            ...req.body,
            preco 
        }

        const livroDao = new LivroDao(db);

        livroDao.adiciona(data)
                .then(resp.redirect('/livros'))
                .catch(erro => console.log(erro));
    });

Dessa forma conseguimos formatar o valor para o usuário, ao mesmo tempo em que mantemos o valor no formato numérico em nosso banco de dados!

Acredito que para formatar dessa maneira, essa será a forma mais eficiente.

Abraços!