I have a table where there is one input box in each row. There are 3 rows in total and i need to calculate the total from those three input boxes value. But the state of value is not updating. I only get the initial state of value. For example, there is a state object of agent, hotel, admin. If i initialize the agent value 10, i get 10 in input box but when i try to change the value i only get 10. The value does not gets updated.
Here is the code
const Tbody = ({ roles, states, onChange, onBlur }) => {
const row = roles.map((role, index) => (
<tr key={index}>
<td>{index + 1}</td>
<td>{role.label}</td>
<td>
<TextFieldGroup
id="formControlsText"
type="number"
name={role.name}
value={states[role.name]}
onChange={event => onChange(event)}
onBlur={event => onBlur(event)}
error={states.errors[role.name]}
required
/>
</td>
</tr>
));
return <tbody>{row}</tbody>;
};
class Commission extends React.PureComponent {
state = {
agentCommission: 0,
hotelCommission: 0,
adminCommission: 0,
errors: {},
isSubmitted: false
};
handleChange = event => {
console.log(event.target);
const fieldName = event.target.name;
this.setState(
{ [event.target.name]: parseFloat(event.target.value) },
() => {
this.validateField([fieldName]);
}
);
};
handleBlur = event => {
const fieldName = event.target.name;
this.validateField([fieldName]);
};
validateField = validate => {
const errors = { ...this.state.errors };
let hasError = false;
validate.forEach(field => {
if (
parseFloat(this.state[field]) > 100 ||
parseFloat(this.state[field]) < 0
) {
hasError = true;
errors[field] = 'cannot be less than 0 and more than 100';
} else {
errors[field] = '';
}
});
this.setState({ errors });
return !hasError;
};
render() {
const { agentCommission, adminCommission, hotelcommission } = this.state;
const totalCommission = agentCommission + adminCommission + hotelcommission;
console.log('totalCommission', totalCommission);
return (
<div className="table-responsive">
<table className="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>S.N</th>
<th>Role</th>
<th>Commission</th>
</tr>
</thead>
<Tbody
roles={[
{ name: 'agentCommission', label: 'Agent' },
{ name: 'hotelCommission', label: 'Hotel Owner' },
{ name: 'adminCommission', label: 'Admin' }
]}
states={{ ...this.state }}
onChange={this.handleChange}
onBlur={this.handleBlur}
/>
<tbody>
<tr>
<td>
<button
className="btn btn-primary"
onClick={this.handleSubmit}
disabled={totalCommission === 100 ? false : true}>
Save Changes
</button>
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
In ReactJS, when you extend a React component class, you must initialize the state in the constructor. Also, you need to call the parent class' constructor via super(props). This is the only way that the React library's class can get access to your state values, as well as provide access in methods such as setState()
https://codepen.io/julianfresco/pen/ybrZNe/
class Commission extends React.PureComponent {
constructor(props, context) {
super(props)
this.state = {
agentCommission: 0,
hotelCommission: 0,
adminCommission: 0,
errors: {},
isSubmitted: false
};
// method instance bindings
this.handleChange = this.handleChange.bind(this)
this.handleBlur = this.handleBlur.bind(this)
this.validateField = this.validateField.bind(this)
}
// ...
// you had 1 typo in the render function, hotelCommission wasn't camel case
render() {
const { agentCommission, adminCommission, hotelCommission } = this.state;
// ...
}
}
The issue is the Commission class, where you are not initializing the state.
Your code should be like the following:
const Tbody = ({ roles, states, onChange, onBlur }) => {
const row = roles.map((role, index) => (
<tr key={index}>
<td>{index + 1}</td>
<td>{role.label}</td>
<td>
<input
id="formControlsText"
type="number"
name={role.name}
value={states[role.name]}
onChange={event => onChange(event)}
onBlur={event => onBlur(event)}
error={states.errors[role.name]}
required
/>
</td>
</tr>
));
return <tbody>{row}</tbody>;
};
class Commission extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
agentCommission: 0,
hotelCommission: 0,
adminCommission: 0,
errors: {},
isSubmitted: false
};
}
handleChange(event) {
console.log(event.target);
const fieldName = event.target.name;
this.setState(
{ [event.target.name]: parseFloat(event.target.value) },
() => {
this.validateField([fieldName]);
}
);
};
handleBlur(event) {
const fieldName = event.target.name;
this.validateField([fieldName]);
};
validateField(validate) {
const errors = { ...this.state.errors };
let hasError = false;
validate.forEach(field => {
if (
parseFloat(this.state[field]) > 100 ||
parseFloat(this.state[field]) < 0
) {
hasError = true;
errors[field] = 'cannot be less than 0 and more than 100';
} else {
errors[field] = '';
}
});
this.setState({ errors });
return !hasError;
};
render() {
const { agentCommission, adminCommission, hotelcommission } = this.state;
const totalCommission = agentCommission + adminCommission + hotelcommission;
console.log('totalCommission', totalCommission);
return (
<div className="table-responsive">
<table className="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>S.N</th>
<th>Role</th>
<th>Commission</th>
</tr>
</thead>
<Tbody
roles={[
{ name: 'agentCommission', label: 'Agent' },
{ name: 'hotelCommission', label: 'Hotel Owner' },
{ name: 'adminCommission', label: 'Admin' }
]}
states={{ ...this.state }}
onChange={this.handleChange}
onBlur={this.handleBlur}
/>
<tbody>
<tr>
<td>
<button
className="btn btn-primary"
onClick={this.handleSubmit}
disabled={totalCommission === 100 ? false : true}>
Save Changes
</button>
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
Fiddle demo: https://codesandbox.io/s/KO3vDRGjR
Related
The code that I posted below is the API request from which I make a table. This table has 4 columns: id, userid, title. I want to understand how I can sort by userid and title, as shown in the photo. It would be great if the steps were described in detail.
I'm trying to group the tab as shown in the photo, but I can't.
Can you suggest/show me how to do this?
Also wanted to know how to reset the group value of a column?
I will be grateful for any help.
My code:
import React from "react";
import "./GroupByUserID.css";
import { Link } from "react-router-dom";
export default class GroupByUserID extends React.Component {
// Constructor
constructor(props) {
super(props);
this.state = {
items: [],
};
}
componentDidMount = () => {
this.apiFetch();
};
//Fetch data from API
apiFetch = () => {
return fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((json) => {
this.setState((prevState) => {
return { ...prevState, items: json };
});
});
};
// Sort UserID
setSortedItemsUserID = () => {
const { items } = this.state;
const sortedUserID = items.sort((a, b) => {
if (a.userId < b.userId) {
return items.direction === "ascending" ? -1 : 1;
}
if (a.userId > b.userId) {
return items.direction === "ascending" ? 1 : -1;
}
return 0;
});
console.log(sortedUserID);
this.setState((prevState) => {
return { ...prevState, items: sortedUserID };
});
};
render() {
const { items } = this.state;
return (
<div>
<h1>Home Page</h1>
<table>
<thead>
<tr>
<th>
<Link target="self" to="/">
View Normal
</Link>
</th>
<th>Group By UserID</th>
</tr>
</thead>
<thead>
<tr>
<th>
User ID
<button
type="button"
onClick={() => this.setSortedItemsUserID()}
>
⬇️
</button>
</th>
<th>Title</th>
</tr>
</thead>
<tbody>
{items.map((item) => (
<tr key={item.userId + item.title}>
<td>{item.userId}</td>
<td>{item.title}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
}
Fairly new with React and wanting to build a simple front end application (no database) with React.
The app is a trivia game and it involves creating "users" which involves a id #, name, a "answers" field to keep track of the answers they've provided and "points" which is an integer of 0 until the player answers a question correctly.
THE PROBLEM is creating a function to add +1 to the users 'answers'. Right now when I complete the function, it saves the state as a object and therefore gives my map() function errors.
My code:
import { Button } from "bootstrap";
import React, { Component, useState } from "react";
import { Header, Table } from "semantic-ui-react";
import NewPlayer from "./NewPlayer";
import DeletePlayer from "./DeletePlayer";
// STATE
class Trivia extends Component {
constructor(props) {
super(props);
this.state = {
players: [{ name: "PLAYER", id: 0, answers: 0, points: 0 }], // Need to change this
};
this.deletePlayer = this.deletePlayer.bind(this);
this.handleChange = this.handleChange.bind(this);
this.addPlayer = this.addPlayer.bind(this);
this.answerYes = this.answerYes.bind(this);
}
// What I want it to do: onClick, add +1 to answers (eventually, add +1 to points)
deletePlayer = (e, nid) => {
e.preventDefault();
var players = this.state.players;
for (var i = 0; i < players.length; i++)
if (players[i].id && players[i].id === nid) {
players.splice(i, 1);
break;
}
this.setState({ players: players });
};
addPlayer = (e) => {
e.preventDefault();
if (!this.state.newPlayerName) {
return;
}
var currentPlayers = this.state.players;
const lastID = currentPlayers[currentPlayers.length - 1];
var variable = lastID.id + 1;
const newPlayer = {
name: this.state.newPlayerName,
id: variable,
answers: 0,
points: 0,
};
this.setState({ players: [...this.state.players, newPlayer] });
document.getElementById("name").value = "";
};
// FUNCTION THAT NEEDS HELP !!!
answerYes = (e, id) => {
// On click, answer goes up +1
e.preventDefault();
var players = this.state.players;
this.setState({ players: this.state.players[id].answers + 1 });
};
answerNo = (e, id) => {
e.preventDefault();
// Subtract point away
};
handleChange(e) {
this.setState({ newPlayerName: e.target.value });
}
render() {
var { players } = this.state;
console.log(players);
return (
<div>
<Header as="h1">Players</Header>
<Table>
<thead>
<tr>
<th>Player #</th>
<th>Name</th>
<th>Answers</th>
<th>Points</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{players.map((player) => {
return (
<tr>
<td>{player.id}</td>
<td>{player.name}</td>
<td>
{player.answers}
<button
onClick={(e) => {
this.answerYes(e, player.id);
}}
>
Correct
</button>
<button
onClick={(e) => {
this.answerNo(e, player.id);
}}
>
Incorrect
</button>{" "}
</td>
<td>{player.points}</td>
<td>
<button
onClick={(e) => {
this.deletePlayer(e, player.id);
}}
>
Delete
</button>
</td>
</tr>
);
})}
</tbody>
</Table>
<div>
<form onSubmit={this.addPlayer}>
<input
type="text"
value={this.state.name}
id="name"
placeholder="add
player name...."
onChange={this.handleChange}
/>
<input type="submit" value="add player" />
</form>
</div>
</div>
);
}
}
export default Trivia;
Right now the error I am getting is : Uncaught TypeError: players.map is not a function. I need help saving the state object. Thank you
The problem is that you are trying to map var players which does not exist before clicking button
<button
onClick={(e) => {
this.answerYes(e, player.id);
}}>
You should change the logic with your requirement flow or alternatively you can assign var player at first render in useEffect then can change in function
useEffect(() => {
var player = this.state.players
}, [] )
I'm trying to create a CRUD application in react, and I have encountered several problems.
How can I remove an item from the table?
Is it possible to pass id to Info component in render method? How can I later link it to the element?
Why does the e.PreventDefault () method cause an error when I try to delete?
import React, { Component } from 'react';
const Info = ({ index, login, pass }) => (
<>
<thead>
<tr>
<th>ID</th>
<th>LOGIN</th>
<th>PASSWORD</th>
</tr>
</thead>
<tbody>
<tr>
<td key={index}>{index}{alert(index)}</td>
<td>{login}</td>
<td>{pass}</td>
</tr>
</tbody>
<input type="submit" value='X' onClick={() => this.del(index)}></input>
</>
);
class List extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
login: "",
pass: "",
};
this.add = this.add.bind(this);
this.show = this.show.bind(this);
this.del = this.show.bind(this);
}
add(e) {
e.preventDefault();
this.setState({
[e.target.name]: e.target.value,
});
}
show(e) {
e.preventDefault();
if (!this.state.login.length || !this.state.pass.length) {
return;
}
else {
const newUser = {
login: this.state.login,
pass: this.state.pass,
};
this.setState(state => ({
data: state.data.concat(newUser),
}))
}
}
del(index) {
const tab = this.state.data.filter((temp) => temp.index !== index);
this.setState(({
data: tab
}));
}
render() {
return (
<div>
<form onSubmit={this.show}>
<label>Login</label><br></br><input type='text' name='login' onChange={e => this.add(e)}></input><br></br>
<label>Password</label><br></br><input type='text' name='pass' onChange={e => this.add(e)}></input><br></br>
<input type="submit" value="Add"></input>
</form>
<table>
{this.state.data.map((val, index) => (
<>
<thead>
<tr>
<th>ID</th>
<th>LOGIN</th>
<th>PASSWORD</th>
</tr>
</thead>
<tbody>
<tr>
<td key={index}>{index}</td>
<td>{val.login}</td>
<td>{val.pass}</td>
</tr>
</tbody>
<input type="submit" value='X' onClick={() => this.del(index)}></input>
</>
))}
</table>
</div>
)
}
}
export default List;
There are small corrections in your code.
this.del = this.show.bind(this); should be this.del = this.del.bind(this);
You are trying to remove the element from the state data using index (this.state.data.filter((temp) => temp.index !== index);) but the element inside the data doesn't have an index property.
In that case, you can use splice to delete the element from the data.
class List extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
login: "",
pass: "",
};
this.add = this.add.bind(this);
this.show = this.show.bind(this);
this.del = this.del.bind(this);
}
add(e) {
e.preventDefault();
this.setState({
[e.target.name]: e.target.value,
});
}
show(e) {
e.preventDefault();
if (!this.state.login.length || !this.state.pass.length) {
return;
}
else {
const newUser = {
login: this.state.login,
pass: this.state.pass,
};
this.setState(state => ({
data: state.data.concat(newUser),
}))
}
}
del(index) {
let {data}=this.state
data.splice(index, 1);
this.setState(({
data
}));
}
render() {
return (
<div>
<form onSubmit={this.show}>
<label>Login</label><br></br><input type='text' name='login' onChange={e => this.add(e)}></input><br></br>
<label>Password</label><br></br><input type='text' name='pass' onChange={e => this.add(e)}></input><br></br>
<input type="submit" value="Add"></input>
</form>
<table>
{this.state.data.map((val, index) => (
<React.Fragment>
<thead>
<tr>
<th>ID</th>
<th>LOGIN</th>
<th>PASSWORD</th>
</tr>
</thead>
<tbody>
<tr>
<td key={index}>{index}</td>
<td>{val.login}</td>
<td>{val.pass}</td>
</tr>
</tbody>
<input type="submit" value='X' onClick={() => this.del(index)}></input>
</React.Fragment>
))}
</table>
</div>
)
}
}
ReactDOM.render(<List />, document.querySelector("#app"))
Here is the demo jsFiddle
Hope it helps :)
I have created a component that sorts and filters an HTML table. The functionality is correct but I have a problem where my table renders "No asset records found." but when I click on one of the headers it displays the contents of the data array in state. I am truly stuck and confused on this strange behaviour. I think the problem might be with the filterAssets function because if I change from this:
let filterAssets = this.state.data.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
})
to this:
let filterAssets = this.props.assetManagement.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
})
Here is the code below if it helps
import React, { Component, Fragment } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { getAssetManagement } from '../../actions/asset-management'
class AssetManagement extends Component {
static propTypes = {
assetManagement: PropTypes.array.isRequired,
getAssetManagement: PropTypes.func.isRequired
}
componentDidMount() {
this.props.getAssetManagement()
}
state = {
name: '',
search: '',
data: []
}
sortBy = this.sortBy.bind(this)
compareBy = this.compareBy.bind(this)
onSubmit = e => {
e.preventDefault()
}
onChange = e =>
this.setState({
[e.target.name]: e.target.value
})
updateSearch = e =>
this.setState({
search: e.target.value.substr(0, 20)
})
compareBy(key) {
return (a, b) => {
if (a[key] < b[key]) return -1
if (a[key] > b[key]) return 1
return 0
}
}
sortBy(key) {
let arrayCopy = [...this.props.assetManagement]
this.state.data.sort(this.compareBy(key))
this.setState({ data: arrayCopy })
}
render() {
let filterAssets = this.state.data.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
})
return (
<Fragment>
{/* Search input */}
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text btn-secondary">
<i class="fas fa-search" />
</span>
</div>
<input
className="form-control"
type="text"
placeholder="Search Asset"
onChange={this.updateSearch.bind(this)}
value={this.state.search}
/>
</div>
{/* Asset management table */}
<div className="table-responsive">
<table className="table table-bordered text-center">
<thead>
<tr>
<th onClick={() => this.sortBy('id')}>ID</th>
<th onClick={() => this.sortBy('name')}>Name</th>
</tr>
</thead>
<tbody>
{filterAssets != 0 ? (
filterAssets.map(a => (
<tr key={a.id}>
<td>{a.id}</td>
<td>{a.name}</td>
</tr>
))
) : (
<tr>
<td colSpan={6}>No asset records found.</td>
</tr>
)}
</tbody>
</table>
</div>
</Fragment>
)
}
}
const mapStateToProps = state => ({
assetManagement: state.assetManagement.assetManagement
})
export default connect(
mapStateToProps,
{ getAssetManagement }
)(AssetManagement)
Change filterAssets != 0 to filterAssets.length > 0
One first render:
let filterAssets = this.state.data.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
})
Your this.state.data is empty, only this.props.assetManagement available if you handle redux properly so no wonder it you cannot get anything from filtering.
Btw: filterAssets != 0 is absolutely wrong, so go ahead and change this line first.
When you use the alternative syntax for a React Component without using a constructor you no longer have access to props. So if you go back to using a standard constructor the problem disappears, e.g.:
constructor(props) {
super(props);
this.state = {
name: "",
search: "",
data: this.props.assetManagement
};
this.sortBy = this.sortBy.bind(this);
this.compareBy = this.compareBy.bind(this);
}
The real problem you have here is that you have two source of data: state.data and props.assetManagement - you retrieve from redux and get newest data from props.assetManagement, but when you need to trigger sorting, you make a copy to state.data. Then problem arises since you don't copy from props.assetManagement to state.data until you trigger sortBy function.
A solution for that is to get rid of state.data and store the sorting key in state. You can update, reset that key value, and sorting logic should be apply to props.assetManagement only:
class AssetManagement extends Component {
static propTypes = {
assetManagement: PropTypes.array.isRequired,
getAssetManagement: PropTypes.func.isRequired
}
componentDidMount() {
this.props.getAssetManagement()
}
state = {
name: '',
search: '',
sortingKey: ''
}
sortBy = this.sortBy.bind(this)
compareBy = this.compareBy.bind(this)
onSubmit = e => {
e.preventDefault()
}
onChange = e =>
this.setState({
[e.target.name]: e.target.value
})
updateSearch = e =>
this.setState({
search: e.target.value.substr(0, 20)
})
compareBy(key) {
return (a, b) => {
if (a[key] < b[key]) return -1
if (a[key] > b[key]) return 1
return 0
}
}
sortBy(key) {
if (key !== this.state.sortingKey) {
this.setState({ sortingKey: key });
}
}
render() {
let sortAssets = !!this.state.sortingKey ?
this.props.assetManagement.sort(this.compareBy(this.state.sortingKey)) :
this.props.assetManagement;
let filterAssets = sortAssets.filter(a => {
return a.name.toLowerCase().indexOf(this.state.search) !== -1
});
return (
<Fragment>
{/* Search input */}
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text btn-secondary">
<i class="fas fa-search" />
</span>
</div>
<input
className="form-control"
type="text"
placeholder="Search Asset"
onChange={this.updateSearch.bind(this)}
value={this.state.search}
/>
</div>
{/* Asset management table */}
<div className="table-responsive">
<table className="table table-bordered text-center">
<thead>
<tr>
<th onClick={() => this.sortBy('id')}>ID</th>
<th onClick={() => this.sortBy('name')}>Name</th>
</tr>
</thead>
<tbody>
{filterAssets != 0 ? (
filterAssets.map(a => (
<tr key={a.id}>
<td>{a.id}</td>
<td>{a.name}</td>
</tr>
))
) : (
<tr>
<td colSpan={6}>No asset records found.</td>
</tr>
)}
</tbody>
</table>
</div>
</Fragment>
)
}
}
Sample code: https://codesandbox.io/s/n91pq7073l
I have a dynamic table and for each rows, I want after I select the product name, The price will be displayed and when I put the quantity, The total (price* quantity) column will be displayed also.
My issue is when I select the name of the product for any row, the same price will be displayed for each row on the table, also when I want the total display it's always having NaN as you see below on the figure :
My code :
class AjouterFacture extends Component {
constructor(props) {
super(props);
this.state = {
rowData: [],
Produits: [],
QuantiteF: "",
Prix: [],
id: 0,
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleRowDelete = this.handleRowDelete.bind(this);
this.handleRowAdd = this.handleRowAdd.bind(this);
this.handleselectChange = this.handleselectChange.bind(this);
this.PrixDisplay = this.PrixDisplay.bind(this);
}
componentWillReceiveProps(nextProps) {
console.log("nextProps", nextProps);
}
componentDidMount() {
axios({
method: "get",
url: "/app/getNomprod/",
withCredentials: true,
}).then(response => {
if (response && response.data) {
this.setState({
Produits: response.data
});
}
}).catch(error => console.log(error));
}
handleQuantiteChange(index, value) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy[index] = Object.assign({}, rowDataCopy[index], {
QuantiteF: parseInt(value, 10)
});
this.setState({
rowData: rowDataCopy
});
}
handleselectprdtChange(index, value) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy[index] = Object.assign({}, rowDataCopy[index], {
selectprdt: value
});
this.setState({
rowData: rowDataCopy,
});
render() {
let {
Clients
} = this.state.Clients;
var Cd = {
pointerEvents: 'none'
}
let {
Produits
} = this.state;
let {
rowData
} = this.state.rowData;
let {
Prix
} = this.state.Prix;
return (<div className="animated fadeIn">
<h6> <Label ><strong>Veuillez ajouter au moins un produit : </strong></Label></h6>
<Table responsive style={items} >
<thead style={back}>
<tr>
<th>PRODUIT</th>
<th>QUANTITE</th>
<th>PRIX UNITAIRE</th>
<th>TOTAL</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.rowData.map((data, index) => (
<tr key={index} id={index}>
<td>
{" "} <Input type="select" name="selectprdt" id="selectprdt"
placeholder="Veuillez sélectionner un produit" value={data.selectprdt}
onChange={(e) => this.handleselectprdtChange(index, e.target.value)} >
<option key={-1} hidden>Choisisr un produit</option>
{ this.state.Produits.map((pdt, i) =>
<option key={i}>{pdt.Nomp}</option>
)}
</Input>
</td>
<td><Input type="number"
value={data.QuantiteF || 0} onChange={(e) => this.handleQuantiteChange(index, e.target.value)}/></td>
<td>
{ this.state.Prix.map(pr =>
<p key={index} >{pr.PrixV} </p>
)}
</td>
<td >
<p key={index} className='pa2 mr2 f6'>{(data.QuantiteF || 0) * (parseInt(this.PrixDisplay(data.selectprdt)|| 0))} </p>
</td>
<td>
<Button onClick={(e) => this.handleRowDelete(index)} active style={center} size="sm" color="danger" className="btn-pill" aria-pressed="true">Effacer</Button>
</td>{" "}
</tr>
))}
<tr>
<td/>
<td/>
<td/>
<td/>
<td><Button onClick={this.handleRowAdd} active style={center} size="sm" color="info" className="btn-pill" aria-pressed="true">Ajouter une ligne</Button></td>
</tr>
</tbody>
</Table>
</div>
);
}
PrixDisplay(selectprdt) {
return axios.get("/app/getPrixprod/" + selectprdt).then(response => {
if (response && response.data) {
this.setState({
Prix: response.data
});
}
}).catch(error => {
console.error(error);
});
}
handleRowDelete(row) {
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy.splice(row, 1);
this.setState({
rowData: rowDataCopy
});
}
handleRowAdd() {
let id = this.state.id;
id = id++;
const rowDataCopy = this.state.rowData.slice(0);
rowDataCopy.push({
selectprdt: "",
QuantiteF: 0,
Prix: ""
});
this.setState({
rowData: rowDataCopy,
id: id
});
}
}
export default AjouterFacture;
How can I fix that please ?
About showing price. You are not saving the price(concatanating). Rather resetting it inside PrixDisplay. So inside state.Prix you have only one value. You probably need to parse into state.rowData[i].Prix. And show actually it inside render. Remove the altogether state.Prix.
About the NaN. Because your PrixDisplay function return Promise it can not be parsed. So NaN. Understand first issue and solution. The second will come with it.
Also, as a suggestion, please look to map, filter methods of Array and try to refactore. It will make you code more pleasant and concise.