Resetting state based upon choice - javascript

I have a custom component that allows for my dropdowns to be generated via the backend, however i need to somehow store the two dropdown values in state, currently i am setting contractType to a value of 10 to meet the conditions of my conditional below, however when selecting a second value which is not 10 state is not reset, how could i achieve a change between two separate state values?
my code
const [contractType, setContractType] = useState(10);
function handleChange(event) {
setContractType(oldValues => ({
...oldValues,
[event.target.name]: event.target.value,
}));
}
my component below
<Search
type="procurementType"
name="procurementType"
label="Procurement Type"
id="procurementTypeId"
onChange={handleChange}
value={contractType}
/>
finally my if statement relating to the decision
{contractType == 10 ? <div className={classes.tableWrapper}>
<Table className={classes.table}>
<TableHead>
<TableRow >
<TableCell>ID</TableCell>
<TableCell>Internal Ref</TableCell>
<TableCell>Title</TableCell>
<TableCell>Organisation</TableCell>
</TableRow>
</TableHead>
<TableBody>
{localContracts.map(row => (
<TableRow className={classes.tableRow}>
<TableCell className={classes.tableCell}>{row.id}</TableCell>
<TableCell>{row.internalRef}</TableCell>
<TableCell>{row.title}</TableCell>
<TableCell>{row.organisationId}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div> : <Table className={classes.table}>
<TableHead>
<TableRow >
<TableCell>ID</TableCell>
<TableCell>Internal Ref</TableCell>
<TableCell>Title</TableCell>
<TableCell>Organisation</TableCell>
</TableRow>
</TableHead>
<TableBody>
{frameworkContracts.map(row => (
<TableRow className={classes.tableRow}>
<TableCell className={classes.tableCell}>{row.id}</TableCell>
<TableCell>{row.internalRef}</TableCell>
<TableCell>{row.title}</TableCell>
<TableCell>{row.organisationId}</TableCell>
</TableRow>
))}
</TableBody>
</Table>}

Related

How to use group table material ui in reactjs?

I use table material UI and
useEffect(() => {
if (props.grouping){
const { groupProperty, rows } = props;
const groups = props.rows.reduce((acc, row) => {
acc[row[groupProperty]] = acc[row[groupProperty]] || [];
acc[row[groupProperty]].push(row);\
return acc;
}, {});
setGroups(groups)
const keys = Object.keys(groups);
setDataGroup(keys)
}
}, [props.rows,props.schema]);
<TableBody>
<>
{props.grouping && (
dataGroup.map(key => (
<TableRow className={clsx(classes.row, props.rowClassName)}>
<TableCell colspan="5">
<CardActions disableActionSpacing>
<b>
{key}
</b>
<IconButton
className={expanded[key] ? classes.expandOpen : classes.expand}
onClick={() => handleExpandClick(key)}
aria-expanded={expanded[key]}
aria-label="Show more"
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
<Collapse in={expanded[key]} timeout="auto" unmountOnExit>
<MuiTable {...other}>
<TableBody>
{groups[key].map(row => (
<TableRow >
<TableCell >{row.wageTitle}</TableCell>
<TableCell numeric>{row.buy}</TableCell>
<TableCell numeric>{row.sell}</TableCell>
<TableCell numeric>{row.buyMaximum}</TableCell>
<TableCell numeric>{row.sellMaximum}</TableCell>
</TableRow>
)
)}
</TableBody>
</MuiTable>
</Collapse>
</TableCell>
</TableRow>
))
)}
.....
<Table grouping={true} rows={tableData} className={classes.table} schema={schema} groupProperty="deductionTypeTitle" ></Table>
I use this link How to group table in reactjs?
..But I want this grouping to be based on two data like this: https://codesandbox.io/s/l9ijbc?file=/demo.js
Someone can help me

Error: Cannot read property 'map' of undefined (state) inside render method

In my project I have a table from react material ui. I am getting an error while filling this table when I use data from state to fill the table. The error is cannot read property 'map' of undefined. The line where it occurs will be marked in the code snippet below.
Here is my code (the error is in the JSX render method):
class AllBooks extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: []
};
}
componentDidMount() {
console.log('component mounted!');
axios.get('http://localhost:8080/all-books').then(allBooks => {
console.log(allBooks.data);
this.setState({
rows: allBooks
});
});
}
onAddButtonClick = (row) => {
console.log('onAddButton click!');
console.log(row);
//axios.post('http://localhost:8080/addBookToRentedBooks', { email: this.state.email,
title: this.state.title, message: this.state.message }).then();
}
test = () => {
console.log(this.state.rows.data);
this.state.rows.data.map(row => console.log(row));
}
render() {
return (
<div>
<Grid container spacing={3}>
<Grid item xs={6} sm={3}></Grid>
<Grid item xs={6} sm={6}>
<h1 style={{textAlign: 'center'}}>All Books</h1>
<br /><br />
<TableContainer component={Paper}>
<Table aria-label="simple table">
<TableHead>
<TableRow>
<TableCell >Title</TableCell>
<TableCell align="right">Author</TableCell>
<TableCell align="right">ISBN</TableCell>
<TableCell align="right">Year</TableCell>
<TableCell align="center">Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.state.rows.data.map((row) => (
<TableRow key={row.name}>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell align="right">z</TableCell>
<TableCell align="right">z</TableCell>
<TableCell align="right">z</TableCell>
<TableCell align="center">
<IconButton onClick={ () => this.onAddButtonClick(row) }>
<AddCircleOutlineIcon />
</IconButton>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Grid>
<Grid item xs={6} sm={3}><button onClick={this.test}>click me</button></Grid>
</Grid>
</div>
)
}
}
I wonder why this.state.rows.data is marked as undefined because I added a simple button - when i click this button, the test method gets called and prints out this.state.rows correctly.
What did I do wrong?
Thanks for every help!
Because initial of state rows is []. so when fetching data this.state.rows.data will be undefined.
You can use optional chaining to check it has value or not before using map:
this.state.rows.data?.map(...)

How to display all db items on a table

I want to retrive all items from the database then display users on a table
Users should be displayed like this:
I can display just the current user and here is my code :
const API_URL = "http://localhost:8080/api/auth/";
class AuthService {
getCurrentUser() {
return JSON.parse(localStorage.getItem('user'));;
}
const currentUser = AuthService.getCurrentUser();
<TableBody>
{this.state.users.map(row => (
<TableRow key={row.id}>
<TableCell component="th" scope="row">
{currentUser.id}
</TableCell>
<TableCell align="right">{currentUser.username}</TableCell>
<TableCell align="right">{currentUser.email}</TableCell>
<TableCell align="right">{currentUser.roles}</TableCell>
</TableRow>
I am assuming that your data is already loaded and you need to pass that data into your react component. I'd recommend to stick to functional components nowadays, since via hooks you can write the same logic as in class based components.
function MyTableComponent(props) {
return (
<TableBody>
{props.users.map(user => (
<TableRow key={row.id}>
<TableCell component="th" scope="row">
{user.id}
</TableCell>
<TableCell align="right">{user.username}</TableCell>
<TableCell align="right">{user.email}</TableCell>
<TableCell align="right">{user.roles}</TableCell>
</TableRow>
)}
</TableBody>
)}
Then you can use that component in your template and pass the props like so:
<MyTableComponent users={myUsersArray} />

How to hide/show column based on if statement using Material-ui?

I have the following code, and I want to hide or show the TableCell based on if statement, how do I do that?
I am using MATERIAL-UI : https://material-ui.com/
<TableBody>
{Object.entries(servicesCode).map(([key, value]) => (
servicesValueTotal[key] = ((servicesValue[key] + servicesTaxe[key])),
<TableRow key={servicesCode[key]}>
<TableCell component="th" scope="row">
{key}
</TableCell>
<TableCell align="center" >{servicesCode[key]}</TableCell>
<TableCell align="center">{servicesValue[key]}</TableCell>
<TableCell align="center">{servicesTaxe[key]}</TableCell>
<TableCell align="center">{servicesValueTotal[key]}</TableCell>
<TableCell align="center">{servicesTec[key]}</TableCell>
<TableCell align="center">{servicesClient[key]}</TableCell>
<TableCell align="center">{servicesStatus[key]}</TableCell>
</TableRow>
))}
</TableBody>
let showTableCell = (true) ? true : false; // you can have a single line condition or multiple line condition using if and else here.
<TableBody>
{Object.entries(servicesCode).map(([key, value]) => (
servicesValueTotal[key] = ((servicesValue[key] + servicesTaxe[key])),
<TableRow key={servicesCode[key]}>
<TableCell component="th" scope="row">
{key}
</TableCell>
{showTableCell && <TableCell align="center" >{servicesCode[key]}</TableCell>}
// or you could also add condition here as well
{showTableCell ? <TableCell align="center">{servicesValue[key]}</TableCell> : "Some other data here"}
<TableCell align="center">{servicesTaxe[key]}</TableCell>
<TableCell align="center">{servicesValueTotal[key]}</TableCell>
<TableCell align="center">{servicesTec[key]}</TableCell>
<TableCell align="center">{servicesClient[key]}</TableCell>
<TableCell align="center">{servicesStatus[key]}</TableCell>
</TableRow>
))}
</TableBody>
Why not use the feature called conditional rendering?
{condition && <Component />},
for example {condition && <TableCell align="center" >{servicesCode[key]}</TableCell>}
Note: As You are using a table to display data, it should have fixed number of th tags - table headings, thus removing table cells completely might be a bad solution.
You could also leave the table cell empty based on conditon like
<TableCell align="center" >{condition && servicesCode[key]}</TableCell> or like <TableCell align="center" >{condition ? someVariable : "No data here"}</TableCell>

Table ordering with a map

I am trying to populate my table, i am calling my api and doing the following
const addressTd = addressesInfo.map(item => (
<TableRow>
<TableCell align="right">{item.officeName}</TableCell>
<TableCell align="right">{item.address1}</TableCell>
</TableRow>));
then within my return I do the following
<Table>
<TableHead>
<TableRow>
<TableCell>Office Name</TableCell>
<TableCell>Address Line 1</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableCell>{addressTd}</TableCell>
</TableBody>
</Table>
however this does not give the desired affect
How could i allow office street to actually render under address? Thankyou
You are actually rendering all rows inside a cell. Here's the fixed version:
const addressTrs = addressesInfo.map((item, i) =>
<TableRow key={i}>
<TableCell align="right">{item.officeName}</TableCell>
<TableCell align="right">{item.address1}</TableCell>
</TableRow>
);
<Table>
<TableHead>
<TableRow>
<TableCell>Office Name</TableCell>
<TableCell>Address Line 1</TableCell>
</TableRow>
</TableHead>
<TableBody>
{addressTrs}
</TableBody>
</Table>
Also it's mandatory to have an unique key if you have an array of elements.

Categories

Resources