Estou fazendo um site de organização financeira, integrado com Sql Server para receber dados. O tipo dos valores que são dinheiro, está como Numeric no banco, assim na web recebia os valores nesse formato (ex: 2500.25). Depois formatei para o formato brasileiro para ficar mais agradável ao usuário (ex: R$ 2.500,25).
Agora como posso filtrar e remover alguns valores para poder salvar novamente e não dar erro no backend ? (Exemplo: R$ 2.500,25 para 2500.25).
Código do input dos valores:
<label> Valor do Ativo: </label>
<input
type="text"
id="valorGanho"
placeholder="Valor do Ganho"
className="form-input"
name="valorGanho"
onInput={e => this.mascaraMoeda(e)}
value={this.state.ganho.valorGanho}
onChange={e => this.atualizaCampo(e)}
/>
Código em que os valores são formatados:
mascaraMoeda(event) {
const onlyDigits = event.target.value
.split("")
.filter(s => /\d/.test(s))
.join("")
.padStart(3, "0")
const digitsFloat = onlyDigits.slice(0, -2) + "." + onlyDigits.slice(-2)
event.target.value = this.maskCurrency(digitsFloat)
}
maskCurrency(valor, locale = 'pt-BR', currency = 'BRL') {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency
}).format(valor)
}
Código do método atualizaCampo e dos que são chamados quando clico em salvar:
salvar() {
const ganho = this.state.ganho
const metodo = ganho.id ? 'put' : 'post'
const url = ganho.id ? `${urlAPI}/${ganho.id}` : urlAPI
axios[metodo](url, ganho)
.then(resp => {
const lista = this.getListaAtualizada(resp.data)
this.setState({ ganho: initialState.ganho, lista })
})
}
getListaAtualizada(ganho, add = true) {
const lista = this.state.lista.filter(g => g.id !== ganho.id)
if (add) lista.unshift(ganho)
return lista
}
atualizaCampo(event) {
const ganho = { ...this.state.ganho }
ganho[event.target.name] = event.target.value
this.setState({ ganho })
}
Já tentei no método atualizaCampo adicionar o método replace na variável ganho, mas sem sucesso.
minha dica: use inputs controlados.
construct(props) {
super(props)
this.state = { ganho: '' }
}
controlarInputGanho(evt) {
this.setState({ ganho: evt.target.value })
}
mascaraMoeda(value) {
const onlyDigits = value
.split("")
.filter(s => /\d/.test(s))
.join("")
.padStart(3, "0")
const digitsFloat = onlyDigits.slice(0, -2) + "." + onlyDigits.slice(-2)
return this.maskCurrency(digitsFloat)
}
maskCurrency(valor, locale = 'pt-BR', currency = 'BRL') {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency
}).format(valor)
}
dai no input:
<input
...
onChange={this.controlarInputGanho}
value={this.mascaraValor(this.state.ganho)}
/>
dessa forma, seu ganho vai aparecer mascarado, mas os dados brutos sempre vão estar no this.state.ganho
e vc n precisa ficar modificando eles
Entendi, não tinha pensado nisso. Mas quando chamo a mascaraMoeda no value é retornado um erro (TypeError: Cannot read properties of undefined (reading ‘value’)). Eu posso colocar condição dentro do value, para que não fique vazio enquanto o usuário não digita?
const urlAPI = "http://localhost:5165/api/ganho"
const initialState = {
ganho: { id: 0, nomeGanho: '', valorGanho: '' },
lista: []
}
export default class CrudGanho extends Component {
state = { ...initialState }
componentDidMount() {
axios(urlAPI).then(resp => {
this.setState({ lista: resp.data })
})
}
limpar() {
this.setState({ ganho: initialState.ganho })
}
salvar() {
const ganho = this.state.ganho
const metodo = ganho.id ? 'put' : 'post'
const url = ganho.id ? `${urlAPI}/${ganho.id}` : urlAPI
axios[metodo](url, ganho)
.then(resp => {
const lista = this.getListaAtualizada(resp.data)
this.setState({ ganho: initialState.ganho, lista })
})
}
getListaAtualizada(ganho, add = true) {
const lista = this.state.lista.filter(g => g.id !== ganho.id)
if (add) lista.unshift(ganho)
return lista
}
atualizaCampo(event) {
const ganho = { ...this.state.ganho }
ganho[event.target.name] = event.target.value
this.setState({ ganho })
}
mascaraMoeda(event) {
const onlyDigits = event.target.value
.split("")
.filter(s => /\d/.test(s))
.join("")
.padStart(3, "0")
const digitsFloat = onlyDigits.slice(0, -2) + "." + onlyDigits.slice(-2)
event.target.value = this.maskCurrency(digitsFloat)
}
maskCurrency(valor, locale = 'pt-BR', currency = 'BRL') {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency
}).format(valor)
}
carregar(ganho) {
this.setState({ ganho })
}
remover(ganho) {
const url = urlAPI + "/" + ganho.id;
if (window.confirm("Confirma remoção do ativo: " + ganho.nomeGanho)) {
console.log("entrou no confirm");
axios['delete'](url, ganho)
.then(resp => {
const lista = this.getListaAtualizada(ganho, false)
this.setState({ ganho: initialState.ganho, lista })
})
}
}
renderTable() {
return (
<div className="financeCard">
<div className="inclui-container">
<label> Nome do Ativo: </label>
<input
type="text"
id="nomeGanho"
placeholder="Nome do Ativo"
className="form-input"
name="nomeGanho"
value={this.state.ganho.nomeGanho}
onChange={e => this.atualizaCampo(e)}
/>
<label> Valor do Ativo: </label>
<input
type="text"
id="valorGanho"
placeholder="Valor do Ativo"
className="form-input"
name="valorGanho"
onInput={e => this.mascaraMoeda(e)}
value={this.mascaraMoeda(this.state.ganho)}
onChange={e => this.atualizaCampo(e)}
/>
Pra funcionar vc tem q mudar o estado, não mexa na variavel event
pra alterar o valor do input.
dá uma lida aqui: https://reactjs.org/docs/forms.html#controlled-components
Ainda estou testando aqui. Estudando também props e componentes controlados, é a primeira vez que estou usando, mas já tinha estudado a teoria antes.
Quando coloco a classe constructor, é devolvido um erro que o método .map na tabela não é um método. E quando faço as alterações que me recomendou é retornado um erro no método de mácara.
Minha classe até aqui:
import React, { Component } from 'react'
import axios from 'axios'
import './CrudGanho.css'
import Main from '../template/Main'
import editButton from '../../assets/images/editButton.svg'
import deleteButton from '../../assets/images/deleteButton.svg'
const urlAPI = "http://localhost:5165/api/ganho"
const initialState = {
ganho: { id: 0, nomeGanho: '', valorGanho: 0 },
lista: []
}
export default class CrudGanho extends Component {
state = { ...initialState }
componentDidMount() {
axios(urlAPI).then(resp => {
this.setState({ lista: resp.data })
})
}
controlarInputGanho(evt) {
this.setState({ ganho: evt })
}
limpar() {
this.setState({ ganho: initialState.ganho })
}
salvar() {
const ganho = this.state.ganho
const metodo = ganho.id ? 'put' : 'post'
const url = ganho.id ? `${urlAPI}/${ganho.id}` : urlAPI
axios[metodo](url, ganho)
.then(resp => {
const lista = this.getListaAtualizada(resp.data)
this.setState({ ganho: initialState.ganho, lista })
})
}
getListaAtualizada(ganho, add = true) {
const lista = this.state.lista.filter(g => g.id !== ganho.id)
if (add) lista.unshift(ganho)
return lista
}
atualizaCampo(event) {
const ganho = { ...this.state.ganho }
ganho[event.target.name] = event.target.value
this.setState({ ganho })
}
mascaraMoeda(value) {
const onlyDigits = value.toString()
.split("")
.filter(s => /\d/.test(s))
.join("")
.padStart(3, "0")
const digitsFloat = onlyDigits.slice(0, -2) + "." + onlyDigits.slice(-2)
return this.maskCurrency(digitsFloat)
}
maskCurrency(valor, locale = 'pt-BR', currency = 'BRL') {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency
}).format(valor)
}
carregar(ganho) {
this.setState({ ganho })
}
remover(ganho) {
const url = urlAPI + "/" + ganho.id;
if (window.confirm("Confirma remoção do ativo: " + ganho.nomeGanho)) {
console.log("entrou no confirm");
axios['delete'](url, ganho)
.then(resp => {
const lista = this.getListaAtualizada(ganho, false)
this.setState({ ganho: initialState.ganho, lista })
})
}
}
renderTable() {
return (
<div className="financeCard">
<div className="inclui-container">
<label> Nome do Ativo: </label>
<input
type="text"
id="nomeGanho"
placeholder="Nome do Ativo"
className="form-input"
name="nomeGanho"
value={this.state.ganho.nomeGanho}
onChange={e => this.atualizaCampo(e)}
/>
<label> Valor do Ativo: </label>
<input
type="text"
id="valorGanho"
placeholder="Valor do Ativo"
className="form-input"
name="valorGanho"
//onInput={e => this.mascaraMoeda(e)}
value={this.mascaraValor(this.state.ganho)}
onChange={this.controlarInputGanho }
/>
<button className="btn"
onClick={e => this.salvar(e)} >
Salvar
</button>
<button className="btn"
onClick={e => this.limpar(e)} >
Cancelar
</button>
</div>
<div className="listagem">
<table className="listaGanhos" id="tblListaGanhos">
<thead>
<tr className="cabecTabela">
<th className="tabTituloNome" id='tab'>Nome do Ativo</th>
<th className="tabTituloValor" id='tab'>Valor do Ativo</th>
</tr>
</thead>
<tbody>
{this.state.lista.map(
(ganho) =>
<tr key={ganho.id}>
<td id='nomeGanho'>{ganho.nomeGanho}</td>
<td id='valorGanho'>{ganho.valorGanho.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })}</td>
<td id='editButton'>
<div className="edit-button" onClick={() => this.carregar(ganho)}>
<img src={editButton} alt="Editar" />
</div>
</td>
<td id='deleteButton'>
<div className="delete-button" onClick={() => this.remover(ganho)}>
<img src={deleteButton} alt="Deletar" />
</div>
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
)
}
render() {
return (
<Main>
{this.renderTable()}
</Main>
)
}
}
Peço perdão, eu errei o nome da função na minha resposta.
Seria this.mascaraMoeda(this.state.ganho)