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

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>

Related

TypeError: language.map is not a function when getting data using axios

This is my component here I'm using MUI for table. I'm getting data from API and I also use map method to get my data but I'm getting error that says:
TypeError: language.map is not a function
But when put language in square it does not error but also not show any data on UI according to me my code is correct can anyone help me.
Language.js
import Table from "#mui/material/Table";
import TableBody from "#mui/material/TableBody";
import TableCell from "#mui/material/TableCell";
import TableContainer from "#mui/material/TableContainer";
import TableHead from "#mui/material/TableHead";
import TableRow from "#mui/material/TableRow";
import Paper from "#mui/material/Paper";
import axios from "axios";
import { useState, useEffect } from "react";
const Languages = () => {
const [language, setLanguage] = useState([]);
useEffect(() => {
axios
.get(
"https://omxdgcc23c.execute-api.ap-south-1.amazonaws.com/dev/api/misc/languages?
userId=0x60588910"
)
.then((res) => {
console.log(res.data);
setLanguage(res.data);
})
.catch((err) => {
console.log(err);
});
}, []);
return (
<div>
<h1>Languages</h1>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell>Id</TableCell>
<TableCell align="right">English Text</TableCell>
<TableCell align="right"> Text</TableCell>
<TableCell align="right">Category</TableCell>
<TableCell align="right">Order Index</TableCell>
<TableCell align="right">Language Code</TableCell>
<TableCell align="right">Created Time</TableCell>
<TableCell align="right">Updated Time</TableCell>
</TableRow>
</TableHead>
<TableBody>
{language.map((languages) => {
return (
<TableRow key={languages.id}>
<TableCell component="th" scope="row">
{languages.uid}
</TableCell>
<TableCell align="right">{languages.engText}</TableCell>
<TableCell align="right">{languages.text}</TableCell>
<TableCell align="right">{languages.category}</TableCell>
<TableCell align="right">{languages.index}</TableCell>
<TableCell align="right">{languages.code}</TableCell>
<TableCell align="right">{languages.createdAt}</TableCell>
<TableCell align="right">{languages.updatedAt}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
</div>
);
};
export default Languages;
See the axios API here, the fetched data is also stored in the data property, so you have to access it like this:
axios.get('...').then(res => setLanguage(res.data.data));
Check the length of language state, if it is greater than 0 after only you can map the language array,
Kindly, check with below code,
{ language && language.length > 0 && language.map((languages) => {
return (
<TableRow key={languages.id}>
<TableCell component="th" scope="row">
{languages.uid}
</TableCell>
<TableCell align="right">{languages.engText}</TableCell>
<TableCell align="right">{languages.text}</TableCell>
<TableCell align="right">{languages.category}</TableCell>
<TableCell align="right">{languages.index}</TableCell>
<TableCell align="right">{languages.code}</TableCell>
<TableCell align="right">{languages.createdAt}</TableCell>
<TableCell align="right">{languages.updatedAt}</TableCell>
</TableRow>
);
})}
The api response is of the format:
{
"statusCode": 200,
"data": [
{...},
{...}
]
}
So when setting languages you need to save the data property of the response's data object.
setLanguage(_.get(res, 'data.data', []));
Then, languages will always be a list, and you won't need to check it throughout the rest of your function.
You may need to check the response in your useEffect block if you want to do some error handling against a bad api response. But that's now in one place rather than throughout the rest of the function.

Table - TypeError: Cannot read property 'map' of undefined Reactjs

I am using material-ui table. I can map the items and display it already however, mapping the orders.items in the table will cause this error:
TypeError: Cannot read property 'map' of undefined
These are the codes:
const [orders, setOrders] = useState([]);
{orders.map((order) => (
<div key={order.id}>
<Typography variant="h6">Ship By:{order.id}</Typography>
<TableContainer>
<Table className={classes.table} aria-label="spanning table">
<TableHead>
<TableRow>
<TableCell align="center" colSpan={3}>
Details
</TableCell>
<TableCell align="right">Price</TableCell>
</TableRow>
<TableRow>
<TableCell>Desc</TableCell>
<TableCell align="right">Qty.</TableCell>
<TableCell align="right">Unit</TableCell>
<TableCell align="right">Sum</TableCell>
</TableRow>
</TableHead>
<div>
<-------------------This is where the error is----------->
<TableBody>
{orders &&
orders.items.map((item) => (
<TableRow key={item.documentID}>
<TableCell>{item.productName}</TableCell>
</TableRow>
))}
</TableBody>
<-------------------This is where the error is----------->
</div>
</Table>
</TableContainer>
</div>
this is the JSON object
[
{
id: "IYQss7JM8LS4lXHV6twn",
total: 130,
items: [
{
qty: 1,
productPrice: "130",
documentID: "y8PN1cUyIr1sBnyV3Iqj",
productName: "Item1",
},
],
displayName: "Jennie Jenn",
},
];
So at your first render, you will not have items in orders array because it is blank array so when it try to map on order.items it will give error.
To solve this try to use optional chaining like below:-
<TableBody>
{order &&
order.items?.map((item) => (
<TableRow key={item.documentID}>
<TableCell>{item.productName}</TableCell>
</TableRow>
))}
</TableBody>

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} />

Resetting state based upon choice

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>}

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