Want to customise MUI - datatable Toolbar and positioning pagination top - javascript

I am able to hide the toolbar icon but i don't have any idea how to positioning pagination bottom to top my another issue is I am trying to add two button (reset and apply )in view-Column toolbar. have. no idea how to customise the class
here I am sharing image for reference as you can see pagination and filter align top right
I am also sharing my working repo please have a look on it. I would appreciate if someone help me to resolve this issue
codesandbox
import React from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
import { Button } from "#material-ui/core";
import { createMuiTheme, MuiThemeProvider } from "#material-ui/core/styles";
class App extends React.Component {
render() {
const columns = ["Name", "Title", "Location", "Age", "Salary"];
const data = [
["Gabby George", "Business Analyst", "Minneapolis", 30, "$100,000"],
["Aiden Lloyd", "Business Consultant", "Dallas", 55, "$200,000"],
["Jaden Collins", "Attorney", "Santa Ana", 27, "$500,000"],
["Franky Rees", "Business Analyst", "St. Petersburg", 22, "$50,000"],
["Aaren Rose", "Business Consultant", "Toledo", 28, "$75,000"],
[
"Blake Duncan",
"Business Management Analyst",
"San Diego",
65,
"$94,000"
],
["Frankie Parry", "Agency Legal Counsel", "Jacksonville", 71, "$210,000"],
["Lane Wilson", "Commercial Specialist", "Omaha", 19, "$65,000"],
["Robin Duncan", "Business Analyst", "Los Angeles", 20, "$77,000"],
["Mel Brooks", "Business Consultant", "Oklahoma City", 37, "$135,000"],
["Harper White", "Attorney", "Pittsburgh", 52, "$420,000"],
["Kris Humphrey", "Agency Legal Counsel", "Laredo", 30, "$150,000"],
["Frankie Long", "Industrial Analyst", "Austin", 31, "$170,000"],
["Brynn Robbins", "Business Analyst", "Norfolk", 22, "$90,000"],
["Justice Mann", "Business Consultant", "Chicago", 24, "$133,000"],
[
"Addison Navarro",
"Business Management Analyst",
"New York",
50,
"$295,000"
],
["Jesse Welch", "Agency Legal Counsel", "Seattle", 28, "$200,000"],
["Eli Mejia", "Commercial Specialist", "Long Beach", 65, "$400,000"],
["Gene Leblanc", "Industrial Analyst", "Hartford", 34, "$110,000"],
["Danny Leon", "Computer Scientist", "Newark", 60, "$220,000"],
["Lane Lee", "Corporate Counselor", "Cincinnati", 52, "$180,000"],
["Jesse Hall", "Business Analyst", "Baltimore", 44, "$99,000"],
["Danni Hudson", "Agency Legal Counsel", "Tampa", 37, "$90,000"],
["Terry Macdonald", "Commercial Specialist", "Miami", 39, "$140,000"],
["Justice Mccarthy", "Attorney", "Tucson", 26, "$330,000"],
["Silver Carey", "Computer Scientist", "Memphis", 47, "$250,000"],
["Franky Miles", "Industrial Analyst", "Buffalo", 49, "$190,000"],
["Glen Nixon", "Corporate Counselor", "Arlington", 44, "$80,000"],
[
"Gabby Strickland",
"Business Process Consultant",
"Scottsdale",
26,
"$45,000"
],
["Mason Ray", "Computer Scientist", "San Francisco", 39, "$142,000"]
];
const getMuiTheme = () =>
createMuiTheme({
overrides: {
MuiChip: {
root: {
backgroundColor: "lightgrey"
}
},
MuiTableCell: {
head: {
backgroundColor: "lightgray !important"
}
}
}
});
const HeaderElements = () => (
<>
<Button>1</Button>
<Button>2</Button>
</>
);
const options = {
filterType: "dropdown",
responsive: "scroll",
print: false,
download: false,
hover: false,
filter: false,
search: false,
viewColumns: true,
rowsPerPage: [10],
rowsPerPageOptions: false,
jumpToPage: false,
textLabels: {
pagination: {
next: "Next ",
previous: "Previous",
rowsPerPage: "",
displayRows: "ON"
}
},
onChangePage(currentPage) {
console.log({ currentPage });
},
onChangeRowsPerPage(numberOfRows) {
console.log({ numberOfRows });
}
};
return (
<MuiThemeProvider theme={getMuiTheme()}>
<MUIDataTable
title={"ACME Employee list"}
data={data}
columns={columns}
options={{
customToolbar: () => <HeaderElements />
}}
/>
</MuiThemeProvider>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));

import * as React from "react";
import PropTypes from "prop-types";
import { alpha } from "#mui/material/styles";
import Box from "#mui/material/Box";
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 TablePagination from "#mui/material/TablePagination";
import TableRow from "#mui/material/TableRow";
import TableSortLabel from "#mui/material/TableSortLabel";
import Toolbar from "#mui/material/Toolbar";
import Typography from "#mui/material/Typography";
import Paper from "#mui/material/Paper";
import Checkbox from "#mui/material/Checkbox";
import IconButton from "#mui/material/IconButton";
import Tooltip from "#mui/material/Tooltip";
import FormControlLabel from "#mui/material/FormControlLabel";
import Switch from "#mui/material/Switch";
import DeleteIcon from "#mui/icons-material/Delete";
import FormatListBulletedIcon from "#mui/icons-material/FormatListBulleted";
import GridViewIcon from "#mui/icons-material/GridView";
import TuneIcon from "#mui/icons-material/Tune";
import { visuallyHidden } from "#mui/utils";
function createData(name, calories, fat, carbs, protein) {
return {
name,
calories,
fat,
carbs,
protein
};
}
const rows = [
createData("Cupcake", 305, 3.7, 67, 4.3),
createData("Donut", 452, 25.0, 51, 4.9),
createData("Eclair", 262, 16.0, 24, 6.0),
createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
createData("Gingerbread", 356, 16.0, 49, 3.9),
createData("Honeycomb", 408, 3.2, 87, 6.5),
createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
createData("Jelly Bean", 375, 0.0, 94, 0.0),
createData("KitKat", 518, 26.0, 65, 7.0),
createData("Lollipop", 392, 0.2, 98, 0.0),
createData("Marshmallow", 318, 0, 81, 2.0),
createData("Nougat", 360, 19.0, 9, 37.0),
createData("Oreo", 437, 18.0, 63, 4.0)
];
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
return -1;
}
if (b[orderBy] > a[orderBy]) {
return 1;
}
return 0;
}
function getComparator(order, orderBy) {
return order === "desc"
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy);
}
// This method is created for cross-browser compatibility, if you don't
// need to support IE11, you can use Array.prototype.sort() directly
function stableSort(array, comparator) {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) {
return order;
}
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
const headCells = [
{
id: "name",
numeric: false,
disablePadding: true,
label: "Dessert (100g serving)"
},
{
id: "calories",
numeric: true,
disablePadding: false,
label: "Calories"
},
{
id: "fat",
numeric: true,
disablePadding: false,
label: "Fat (g)"
},
{
id: "carbs",
numeric: true,
disablePadding: false,
label: "Carbs (g)"
},
{
id: "protein",
numeric: true,
disablePadding: false,
label: "Protein (g)"
}
];
function EnhancedTableHead(props) {
const {
onSelectAllClick,
order,
orderBy,
numSelected,
rowCount,
onRequestSort
} = props;
const createSortHandler = (property) => (event) => {
onRequestSort(event, property);
};
return (
<TableHead>
<TableRow>
<TableCell padding="checkbox">
<Checkbox
color="primary"
indeterminate={numSelected > 0 && numSelected < rowCount}
checked={rowCount > 0 && numSelected === rowCount}
onChange={onSelectAllClick}
inputProps={{
"aria-label": "select all desserts"
}}
/>
</TableCell>
{headCells.map((headCell) => (
<TableCell
key={headCell.id}
align={headCell.numeric ? "right" : "left"}
padding={headCell.disablePadding ? "none" : "normal"}
sortDirection={orderBy === headCell.id ? order : false}
>
<TableSortLabel
active={orderBy === headCell.id}
direction={orderBy === headCell.id ? order : "asc"}
onClick={createSortHandler(headCell.id)}
>
{headCell.label}
{orderBy === headCell.id ? (
<Box component="span" sx={visuallyHidden}>
{order === "desc" ? "sorted descending" : "sorted ascending"}
</Box>
) : null}
</TableSortLabel>
</TableCell>
))}
</TableRow>
</TableHead>
);
}
EnhancedTableHead.propTypes = {
numSelected: PropTypes.number.isRequired,
onRequestSort: PropTypes.func.isRequired,
onSelectAllClick: PropTypes.func.isRequired,
order: PropTypes.oneOf(["asc", "desc"]).isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired
};
const EnhancedTableToolbar = (props) => {
const {
numSelected,
rowsPerPageOptions,
component,
count,
rowsPerPage,
page,
onPageChange,
onRowsPerPageChange
} = props;
return (
<Toolbar
sx={{
pl: { sm: 2 },
pr: { xs: 1, sm: 1 },
...(numSelected > 0 && {
bgcolor: (theme) =>
alpha(
theme.palette.primary.main,
theme.palette.action.activatedOpacity
)
})
}}
>
{numSelected > 0 ? (
<Typography
sx={{ flex: "1 1 100%" }}
color="inherit"
variant="subtitle1"
component="div"
>
{numSelected} selected
</Typography>
) : (
<Typography
sx={{ flex: "1 1 100%" }}
variant="h6"
id="tableTitle"
component="div"
>
Nutrition
</Typography>
)}
{numSelected > 0 ? (
<Tooltip title="Delete">
<IconButton>
<DeleteIcon />
</IconButton>
</Tooltip>
) : (
<>
<Tooltip title="grid view">
<IconButton>
<GridViewIcon />
</IconButton>
</Tooltip>
<Tooltip title="list view">
<IconButton>
<FormatListBulletedIcon />
</IconButton>
</Tooltip>
<Tooltip title="Advance filter">
<IconButton>
<TuneIcon />
</IconButton>
</Tooltip>
<Tooltip title="pagination">
<IconButton>
<TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component={component}
count={count}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={onPageChange}
onRowsPerPageChange={onRowsPerPageChange}
/>
</IconButton>
</Tooltip>
</>
)}
</Toolbar>
);
};
EnhancedTableToolbar.propTypes = {
numSelected: PropTypes.number.isRequired
};
export default function EnhancedTable() {
const [order, setOrder] = React.useState("asc");
const [orderBy, setOrderBy] = React.useState("calories");
const [selected, setSelected] = React.useState([]);
const [page, setPage] = React.useState(0);
const [dense, setDense] = React.useState(false);
const [rowsPerPage, setRowsPerPage] = React.useState(5);
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === "asc";
setOrder(isAsc ? "desc" : "asc");
setOrderBy(property);
};
const handleSelectAllClick = (event) => {
if (event.target.checked) {
const newSelecteds = rows.map((n) => n.name);
setSelected(newSelecteds);
return;
}
setSelected([]);
};
const handleClick = (event, name) => {
const selectedIndex = selected.indexOf(name);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, name);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1)
);
}
setSelected(newSelected);
};
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
const handleChangeDense = (event) => {
setDense(event.target.checked);
};
const isSelected = (name) => selected.indexOf(name) !== -1;
// Avoid a layout jump when reaching the last page with empty rows.
const emptyRows =
page > 0 ? Math.max(0, (1 + page) * rowsPerPage - rows.length) : 0;
return (
<Box sx={{ width: "100%" }}>
<Paper sx={{ width: "100%", mb: 2 }}>
<EnhancedTableToolbar
numSelected={selected.length}
rowsPerPageOptions={false}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
<TableContainer>
<Table
sx={{ minWidth: 750 }}
aria-labelledby="tableTitle"
size={dense ? "small" : "medium"}
>
<EnhancedTableHead
numSelected={selected.length}
order={order}
orderBy={orderBy}
onSelectAllClick={handleSelectAllClick}
onRequestSort={handleRequestSort}
rowCount={rows.length}
/>
<TableBody>
{/* if you don't need to support IE11, you can replace the `stableSort` call with:
rows.slice().sort(getComparator(order, orderBy)) */}
{stableSort(rows, getComparator(order, orderBy))
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row, index) => {
const isItemSelected = isSelected(row.name);
const labelId = `enhanced-table-checkbox-${index}`;
return (
<TableRow
hover
onClick={(event) => handleClick(event, row.name)}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row.name}
selected={isItemSelected}
>
<TableCell padding="checkbox">
<Checkbox
color="primary"
checked={isItemSelected}
inputProps={{
"aria-labelledby": labelId
}}
/>
</TableCell>
<TableCell
component="th"
id={labelId}
scope="row"
padding="none"
>
{row.name}
</TableCell>
<TableCell align="right">{row.calories}</TableCell>
<TableCell align="right">{row.fat}</TableCell>
<TableCell align="right">{row.carbs}</TableCell>
<TableCell align="right">{row.protein}</TableCell>
</TableRow>
);
})}
{emptyRows > 0 && (
<TableRow
style={{
height: (dense ? 33 : 53) * emptyRows
}}
>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
</Paper>
{/* <FormControlLabel
control={<Switch checked={dense} onChange={handleChangeDense} />}
label="Dense padding"
/> */}
</Box>
);
}
Finally I implemented by myself. how we can archive. I tried and search lots of article even i also check MUi github issues But there is no proper definition available on the internet. hope in future that would help other too

Related

ReactJS mapped choices array based on id

I am pretty new to JavaScript and was hoping someone could help me out with this one.
I have this page that shows all the scheduled exams and when you press on "Learn more" a modal opens up that should let you modify information about the exam itself. At the moment it shows the equipment that is selected when creating the exam plus the rest of the equipment available and you should be able to select/deselect in order to change if needed. The problem is that a different modal opens up for each exam to show the corresponding data only. All the exam information I've got shown through mapping to get to the inside arrays of the "exams" nested array, so I do not know how to initialize a const before the render when I need the modal to be open to get that specific exams' info. At the moment I am mapping the values of the selected equipment which does not let me change the selection like I should.
https://codesandbox.io/s/81xer5
import "./styles.css";
import React, { useState, useEffect } from "react";
import Box from "#mui/material/Box";
import Card from "#mui/material/Card";
import CardActions from "#mui/material/CardActions";
import CardContent from "#mui/material/CardContent";
import Button from "#mui/material/Button";
import Typography from "#mui/material/Typography";
import Modal from "#mui/material/Modal";
import Chip from "#mui/material/Chip";
import OutlinedInput from "#mui/material/OutlinedInput";
import InputLabel from "#mui/material/InputLabel";
import MenuItem from "#mui/material/MenuItem";
import FormControl from "#mui/material/FormControl";
import Select from "#mui/material/Select";
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250
}
}
};
const style = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: "background.paper",
boxShadow: 24,
p: 4,
borderRadius: 1
};
export default function App() {
const [exams, setExams] = useState([
{
id: "18897a8c-bd5b-4fc0-86d1-74ee509d46ee",
name: "New Test",
date: null,
time: null,
date2: "2022-06-20",
time2: "15:30",
students: [
{
id: "749ce920-2462-457a-8af3-26ff9c00dda5",
username: "student1",
email: "student1#gmail.com",
firstName: "Student",
lastName: "Studentov",
roleName: "STUDENT"
},
{
id: "90289548-19bb-480b-81e3-c36340debbc7",
username: "student2",
email: "student2#gmail.com",
firstName: "Student",
lastName: "Studentov",
roleName: "STUDENT"
},
{
id: "dfe50fe5-ef9d-480e-aa6c-2f5c81bb22da",
username: "student3",
email: "student3#gmail.com",
firstName: "Student",
lastName: "Studentov",
roleName: "STUDENT"
}
],
staff: [
{
id: "a3b53ed0-63fc-4f77-a8dc-74915d6aefea",
username: "staff",
email: "staff#gmail.com",
firstName: "Staff",
lastName: "Staffov",
roleName: "STAFF"
}
],
rooms: [
{
id: "a49f18cb-4fe8-4a2c-a665-4361c5401f31",
number: 100,
nrOfSeats: 20
},
{
id: "5c46e888-fce4-4c1b-a8ec-e04d32a5cf6c",
number: 400,
nrOfSeats: 10
}
],
equipment: [
{
id: "08506d1b-30ce-43d2-a0b8-74f87082e356",
name: "Crane",
availability: true
}
]
},
{
id: "65b7ecd2-ba30-4369-9f13-9186dc5cc73c",
name: "Crane Exam",
date: null,
time: null,
date2: null,
time2: null,
students: [
{
id: "749ce920-2462-457a-8af3-26ff9c00dda5",
username: "student1",
email: "student1#gmail.com",
firstName: "Student",
lastName: "Studentov",
roleName: "STUDENT"
},
{
id: "90289548-19bb-480b-81e3-c36340debbc7",
username: "student2",
email: "student2#gmail.com",
firstName: "Student",
lastName: "Studentov",
roleName: "STUDENT"
},
{
id: "dfe50fe5-ef9d-480e-aa6c-2f5c81bb22da",
username: "student3",
email: "student3#gmail.com",
firstName: "Student",
lastName: "Studentov",
roleName: "STUDENT"
}
],
staff: [
{
id: "a3b53ed0-63fc-4f77-a8dc-74915d6aefea",
username: "staff",
email: "staff#gmail.com",
firstName: "Staff",
lastName: "Staffov",
roleName: "STAFF"
}
],
rooms: [
{
id: "a49f18cb-4fe8-4a2c-a665-4361c5401f31",
number: 100,
nrOfSeats: 20
},
{
id: "5c46e888-fce4-4c1b-a8ec-e04d32a5cf6c",
number: 400,
nrOfSeats: 10
}
],
equipment: [
{
id: "08506d1b-30ce-43d2-a0b8-74f87082e356",
name: "Crane",
availability: true
},
{
id: "be1da3c9-7192-459f-bdba-767e005eaac9",
name: "Killer Robot",
availability: true
}
]
}
]);
const [equipment, setEquipment] = useState([
{
id: "08506d1b-30ce-43d2-a0b8-74f87082e356",
name: "Crane",
availability: true
},
{
id: "7a1716c7-3398-4e3d-9523-7ba4a102a79b",
name: "Lift",
availability: true
},
{
id: "be1da3c9-7192-459f-bdba-767e005eaac9",
name: "Killer Robot",
availability: true
}
]);
const initialShowState = Object.fromEntries(
exams.map((data) => [data.id, false])
);
const [show, setShow] = React.useState(initialShowState);
const toggleShow = (id) =>
setShow((prev) => {
return { ...prev, [id]: !prev[id] };
});
console.log({ show });
const [value, setValue] = React.useState([]); //this is what the select chip uses by default
const handleChange = (e) => {
const {
target: { value }
} = e;
console.log(value);
setValue(
// On autofill we get a the stringified value.
typeof value === "string" ? value.split(",") : value
);
};
return (
<div className="App">
{exams.map((data, key) => {
return (
<div key={key} style={{ width: "300px", display: "inline-block" }}>
<Box
sx={{
minWidth: 300,
maxWidth: 300,
display: "inline-block",
paddingTop: "10px",
paddingLeft: "10px"
}}
>
<Card variant="outlined">
<React.Fragment>
<CardContent>
<Typography variant="h5" component="div">
{data.name}
</Typography>
</CardContent>
<CardActions>
<Button size="small" onClick={() => toggleShow(data.id)}>
Learn More
</Button>
</CardActions>
</React.Fragment>
</Card>
</Box>
<Modal open={show[data.id]} onClose={() => toggleShow(data.id)}>
<Box sx={style}>
<Typography
component={"span"}
id="transition-modal-description"
sx={{ mt: 2 }}
>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="demo-multiple-chip-label">Chip</InputLabel>
<Select
multiple
value={data.equipment.map((sub) => sub.id)}
// value={value}
onChange={handleChange}
input={
<OutlinedInput id="select-multiple-chip" label="Chip" />
}
renderValue={(selected) => {
return (
<Box
sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}
>
{selected.map((value) => {
const option = equipment.find(
(o) => o.id === value
);
return <Chip key={value} label={option.name} />;
})}
</Box>
);
}}
MenuProps={MenuProps}
>
{equipment.map((option) => (
<MenuItem key={option.id} value={option.id}>
{option.name}
</MenuItem>
))}
</Select>
</FormControl>
</Typography>
</Box>
</Modal>
</div>
);
})}
</div>
);
}
Continuing my comment above, you're adding a <Modal> inside the map function, this will mount a <Modal> element for each exam, which is bad for performance and more difficult to implement.
What you want to do is to have only one modal, and upon clicking "Learn More" you save the active exam in a state, the modal uses this state to show the correct data. You also want to split the logic between the exam and the modal to make it more easy to implement.
Here is a sample code, I have moved the arrays outside the component to make the code more clear:
const EXAMS = [...];
const EQUIPMENTS = [...];
export default function App() {
const [exams, setExams] = useState(EXAMS);
const [equipment, setEquipment] = useState(EQUIPMENTS);
const [modalExam, setModalExam] = useState(null);
return (
<div className="App">
{exams.map((data, key) => {
return (
<div key={key} style={{ width: "300px", display: "inline-block" }}>
<Box
sx={{
minWidth: 300,
maxWidth: 300,
display: "inline-block",
paddingTop: "10px",
paddingLeft: "10px",
}}
>
<Card variant="outlined">
<React.Fragment>
<CardContent>
<Typography variant="h5" component="div">
{data.name}
</Typography>
</CardContent>
<CardActions>
<Button size="small" onClick={() => setModalExam(data)}>
Learn More
</Button>
</CardActions>
</React.Fragment>
</Card>
</Box>
</div>
);
})}
<ModalExam
equipment={equipment}
exam={modalExam}
onClose={() => setModalExam(null)}
/>
</div>
);
}
function ModalExam({ exam, equipment, onClose }) {
const [chipValue, setChipValue] = useState([]);
useEffect(() => {
if (exam) {
setChipValue(exam.equipment.map((sub) => sub.id));
}
}, [exam]);
const handleChange = (e) => {
const {
target: { value },
} = e;
console.log(value);
setChipValue(typeof value === "string" ? value.split(",") : value);
};
return (
<Modal open={exam !== null} onClose={onClose}>
{exam && (
<Box sx={style}>
<Typography
component={"span"}
id="transition-modal-description"
sx={{ mt: 2 }}
>
<p>{exam.name}</p>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="demo-multiple-chip-label">Chip</InputLabel>
<Select
multiple
value={chipValue}
// value={value}
onChange={handleChange}
input={<OutlinedInput id="select-multiple-chip" label="Chip" />}
renderValue={(selected) => {
return (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const option = equipment.find((o) => o.id === value);
return <Chip key={value} label={option.name} />;
})}
</Box>
);
}}
MenuProps={MenuProps}
>
{equipment.map((option) => (
<MenuItem key={option.id} value={option.id}>
{option.name}
</MenuItem>
))}
</Select>
</FormControl>
</Typography>
</Box>
)}
</Modal>
);
}
See how much simple it gets when you split the logic. Here is the sandbox: https://codesandbox.io/s/hedk9g

There is a problem in making multiple select boxes with react and type scripts

I just made a multi-select box. Selecting one of the upper categories changes the lower category and table. I have made changes, but they should not be changed immediately, but should be modified to change when the search button is pressed. I'm attaching the code below. I wonder where to add the code. Please Help me. ....
import ~
const cx = className.bind(style);
const TableCard = styled(Card)`
padding: 0;
border-radius: 6px;
table {
border-radius: 6px;
tr {
border-radius: 6px;
}
}
`;
export default function ManageLog() {
const [userInfo] = useUserInfo();
const [userInfoLog, setUserInfoLog] = useState({
name: "User Info",
userSeq: 0
});
const [memberType, setMemberType] = useState({
name: "Member Type",
memberSeq: 0
});
const [connectType, setConnectType] = useState({
name: "Connect Type",
connectSeq: 0
});
const [errorLog, setErrorLog] = useState({
name: "Error Log",
errorSeq: 0
});
const userInfoLogDefaultValue = useMemo(() => {
return {
name: "User Info",
userSeq: 0
};
}, []);
const memberTypeDefaultValue = useMemo(() => {
return {
name: "Member Type",
memberSeq: 0
};
}, [userInfoLog.userSeq]);
const connectTypeDefaultValue = useMemo(() => {
return {
name: "Connect Type",
connectSeq: 0
};
}, [userInfoLog.userSeq]);
const errorLogDefaultValue = useMemo(() => {
return {
name: "Error Log",
errorSeq: 0
};
}, [userInfoLog.userSeq]);
const col: ICol[] = [
{
title: "NO",
dataIndex: 'no',
width: "80px"
},{
title: "User ID",
dataIndex: 'userId'
},{
title: "Member Type",
dataIndex: 'memberType'
},{
title: "Company Name",
dataIndex: 'companyName'
},{
title: "Change Type",
dataIndex: 'changeForm',
width: "148px"
},{
title: "Change Time",
dataIndex: 'changeTime'
}
];
const loginCol: ICol[] = [
{
width: "80px",
title: "NO",
dataIndex: "no"
}, {
title: "User ID",
dataIndex: "userId"
}, {
title: "Company Name",
dataIndex: "companyName"
}, {
title: "IP Address",
dataIndex: "ipAddress"
}, {
title: "Connect Time",
dataIndex: "connectTime"
}, {
title: "Connect Type",
dataIndex: "connectType",
render: value => {
if (value === "Login")
return <span className={cx('loginText')}>{"Login"}</span>;
else if (value === "Logout")
return <span className={cx('logoutText')}>{"Logout"}</span>;
else if (value === "LoginFail")
return <span className={cx('loginFail')}>{"LoginFail"}</span>;
else if (value === "session")
return <span className={cx('sessionText')}>{"session"}</span>;
else
return
}
}
];
const errorCol: ICol[] = [
{
width: "80px",
title: "NO",
dataIndex: "no"
}, {
title: "Error Time",
dataIndex: "errorTime"
}, {
title: "Error Page",
dataIndex: "errorPage"
}, {
title: "Error Type",
dataIndex: "errorType"
}
];
const [searchValue, setSearchValue] = useState("");
const [filterDate, setFilterDate] = useState([new Date(), new Date()]);
const [searchOptions, setSearchOptions] = useState(null);
const { isLoading, list, pagination } = useCondDate(searchOptions);
const { page, setPage, setSize, total } = pagination;
const handleSearchData = () => {
console.log(userInfoLog, memberType, connectType, errorLog, filterDate, searchValue)
setSearchOptions({
userInfoLog: userInfoLog.userSeq,
memberType: memberType.memberSeq,
connectType: connectType.connectSeq,
errorKind: errorLog.errorSeq,
startDate: dateFormat(filterDate[0], "yyyy.MM.dd HH:mm:ss"),
endDate: dateFormat(filterDate[1], "yyyy.MM.dd HH:mm:ss")
})
}
return (
<div>
<Row justifyContent="flex-start">
{(userInfo?.type === "aggregator_member" || userInfo?.type === "aggregator") &&
<Col width={180} mr={10}>
<Select
onSelect={v => setUserInfoLog(v)}
options={[
{ name: "User Info", userSeq: 0},
{ name: "Login Log", userSeq: 1},
{ name: "Error Log", userSeq: 2}
]}
defaultValue={userInfoLogDefaultValue}
selectKey="userSeq"
labelKey='name'
/>
</Col>
}
<Col width={105} mr={10}>
{userInfoLog.userSeq === 0 ?
<>
<Select
onSelect={v => setMemberType(v)}
options={[
{ name: "Member Type", memberSeq: 0},
{ name: "Member", memberSeq: 1},
{ name: "Manager", memberSeq: 2}
]}
defaultValue={memberTypeDefaultValue}
selectKey="memberSeq"
labelKey='name'
/>
</>: null}
{userInfoLog.userSeq === 1 ?
<>
<Select
onSelect={v => setConnectType(v)}
options={[
{ name: "User ID", connectSeq: 0},
{ name: "Connect Time", connectSeq: 1},
{ name: "Connect Type", connectSeq: 2}
]}
defaultValue={connectTypeDefaultValue}
selectKey="connectSeq"
labelKey='name'
/>
</> : null}
{userInfoLog.userSeq === 2 ?
<>
<Select
onSelect={v => setErrorLog(v)}
options={[
{ name: "Error Type", errorSeq: 0},
{ name: "404", errorSeq: 1},
{ name: "500", errorSeq: 2}
]}
defaultValue={errorLogDefaultValue}
selectKey="errorSeq"
labelKey='name'
/>
</> : null}
</Col>
<Col width={333} mr={10}>
<DatePicker onChangeDate={date => setFilterDate(date as [Date, Date])}
disabled={false}
isRange={true}
format={"yyyy.MM.dd HH:mm:ss"} />
</Col>
<Col width={150} mr={5}>
<BorderedMiniInput
value={searchValue}
onChange={setSearchValue}
placeholder=" ID"
/>
</Col>
<Col>
<Button
primary={true}
label={""}
size="large"
icon={"icon_input_search2"}
iconSize={18}
bgColor={"#98A3C7"}
hoverColor={"#C7C7E8"}
onClick={() => handleSearchData()}
/>
</Col>
<Col style={{marginLeft: 'auto'}}>
<Button
label={"excel"}
size="large"
icon={"icon_xls"}
iconSize={18}
bgColor={'#fff'}
borderColor={"#24D0AF"}
/>
</Col>
</Row>
{!isLoading && <>
{userInfoLog.userSeq === 0 ?
<>
<Row>
<Col width={'100%'}>
<TableCard>
<Table
data={[
{
no : 1,
userId : "admin001",
memberType : "ann",
companyName : "ann",
changeForm : "ann",
changeTime : "2021.11.06 17:30:00"
},{
no : 2,
userId : "admin002",
memberType : "ann",
companyName : "ann",
changeForm : "ann",
changeTime : "2021.01.06 17:30:00"
},{
no : 3,
userId : "admin003",
memberType : "ann",
companyName : "ann(ann,
changeForm : "ann",
changeTime : "2021.01.31 17:30:00"
},{
no : 4,
userId : "admin004",
memberType : "ann",
companyName : "ann)",
changeForm : "ann",
changeTime : "2021.02.06 17:30:00"
},{
no : 5,
userId : "admin005",
memberType : "ann",
companyName : "ann",
changeForm : "ann",
changeTime : "2021.02.09 17:30:00"
}
]}
col={col}
keyItem="no"
pagination />
</TableCard>
</Col>
</Row>
</>
: null }
{userInfoLog.userSeq === 1 ?
<>
<Row>
<Col width={'100%'}>
<TableCard>
<Table
data={[
{
no : 1,
userId : "admin001",
companyName : "ann",
ipAddress : "123.12.1.0",
connectType : "ann",
connectTime : "2021.11.06 17:30:00"
}
]}
col={loginCol}
keyItem="no"
onPageChange={(page, perPage) => {
setPage(page - 1);
setSize(perPage);
}
}
totalCount={total}
/>
</TableCard>
</Col>
</Row>
</> : null}
{userInfoLog.userSeq === 2 ?
<>
<Row>
<Col width={"100%"}>
<TableCard>
<Table
data={[
{
no : 1,
errorTime : "2022.01.31 17:30:00",
errorPage : "http://localhost8081/order/ordPwTrdList.do",
errorType : "500"
}, {
no : 2,
errorTime : "2022.02.06 17:30:00",
errorPage : "http://localhost8081/order/ordPwTrdList.do",
errorType : "404"
}, {
no : 3,
errorTime : "2022.02.11 17:30:00",
errorPage : "http://localhost8081/order/ordPwTrdList.do",
errorType : "500"
}, {
no : 4,
errorTime : "2022.02.13 17:30:00",
errorPage : "http://localhost8081/order/ordPwTrdList.do",
errorType : "500"
}, {
no : 5,
errorTime : "2022.02.14 17:30:00",
errorPage : "http://localhost8081/order/ordPwTrdList.do",
errorType : "404"
}
]}
col={errorCol}
keyItem="no"
onPageChange={(page, perPage) => {
setPage(page - 1);
setSize(perPage);
}}
totalCount={total}
/>
</TableCard>
</Col>
</Row>
</> : null}
</>}
</div>
)
}
Another option for a multi select would be react-select.
React is a javascript software library and react-select is a component that makes the handling of selects in the application much easier.
Install package:
yarn add react-select
or
npm i --save react-select
This is an example for implementation:
import React, { Component } from 'react'
import Select from 'react-select'
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
const MyComponent = () => (
<Select
isMulti
options={options}
/>
)
If you need more information, please visit: https://react-select.com/home

How to use drag and drop in ant design?

What I want is an example about how to make the drag and drop of my Table that works properly, but I cannot figure out how to make it works in (functional components)
My code :
function Preview() {
const { name } = useParams();
const [fieldsOfForm, setFieldsOfForm] = useState([]);
const [selectedForm, setSelectedForm] = useState([]);
const columns = [
{
title: 'Posição',
dataIndex: 'pos',
width: 30,
className: 'drag-visible',
render: () =>
<MenuOutlined style={{ cursor: 'grab', color: '#999' }}/>
},
{
title: "Form Name",
dataIndex: "field",
key: "field",
render: (text) => <a>{text}</a>,
},
{
title: "Tipo",
dataIndex: "fieldtype",
key: "fieldtype",
},
];
useEffect(() => {
let mounted = true;
let loadingStates = loading;
if (mounted) {
setFieldsOfForm(location.state);
loadingStates.allFields = false;
setLoading(false);
}
return () => (mounted = false);
}, [selectedForm]);
return (
//Some jsx....
<Row gutter={1}>
<Col span={1}></Col>
<Table dataSource={fieldsOfForm}
columns= {columns}/>
</Row>
// More jsx...
);
}
export default Preview;
Everything that I found on internet about this drag and drop from the lib of antd is in class component , but I wanted to make it works in my functional one.
Example that I found :
multi row drag-able table (antd)
I want some example in function component if someone has tried it already and could help me ?
Here's a functional working example:
import React from "react";
import "antd/dist/antd.css";
import { Table } from "antd";
import {
sortableContainer,
sortableElement,
sortableHandle
} from "react-sortable-hoc";
import { MenuOutlined } from "#ant-design/icons";
const data = [
{
key: "1",
name: "John Brown",
age: 32,
address: "New York No. 1 Lake Park",
index: 0
},
{
key: "2",
name: "Jim Green",
age: 42,
address: "London No. 1 Lake Park",
index: 1
},
{
key: "3",
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park",
index: 2
},
{
key: "4",
name: "4",
age: 32,
address: "New York No. 1 Lake Park",
index: 3
},
{
key: "5",
name: "5",
age: 42,
address: "London No. 1 Lake Park",
index: 4
},
{
key: "6",
name: "6",
age: 32,
address: "Sidney No. 1 Lake Park",
index: 5
}
];
const DragHandle = sortableHandle(({ active }) => (
<MenuOutlined style={{ cursor: "grab", color: active ? "blue" : "#999" }} />
));
const SortableItem = sortableElement((props) => <tr {...props} />);
const SortableContainer = sortableContainer((props) => <tbody {...props} />);
function SortableTable() {
const [dataSource, setDataSource] = React.useState(data);
const [selectedItems, setSelectedItems] = React.useState([]);
const getColumns = () => {
return [
{
title: "Sort",
dataIndex: "",
width: 30,
className: "drag-visible",
render: (d, dd, i) => (
<>
<DragHandle active={selectedItems.includes(i)} />
</>
)
},
{
title: "Name",
dataIndex: "name",
className: "drag-visible"
},
{
title: "Age",
dataIndex: "age"
},
{
title: "Address",
dataIndex: "address"
}
];
};
const merge = (a, b, i = 0) => {
let aa = [...a];
return [...a.slice(0, i), ...b, ...aa.slice(i, aa.length)];
};
const onSortEnd = ({ oldIndex, newIndex }) => {
let tempDataSource = dataSource;
if (oldIndex !== newIndex) {
if (!selectedItems.length) {
let movingItem = tempDataSource[oldIndex];
tempDataSource.splice(oldIndex, 1);
tempDataSource = merge(tempDataSource, [movingItem], newIndex);
} else {
let filteredItems = [];
selectedItems.forEach((d) => {
filteredItems.push(tempDataSource[d]);
});
let newData = [];
tempDataSource.forEach((d, i) => {
if (!selectedItems.includes(i)) {
newData.push(d);
}
});
tempDataSource = [...newData];
tempDataSource = merge(tempDataSource, filteredItems, newIndex);
}
setDataSource(tempDataSource);
setSelectedItems([]);
}
};
const DraggableContainer = (props) => (
<SortableContainer
useDragHandle
disableAutoscroll
helperClass="row-dragging"
onSortEnd={onSortEnd}
{...props}
/>
);
const DraggableBodyRow = ({ className, style, ...restProps }) => {
// function findIndex base on Table rowKey props and should always be a right array index
const index = dataSource.findIndex(
(x) => x.index === restProps["data-row-key"]
);
return (
<SortableItem
index={index}
{...restProps}
selected={selectedItems.length}
onClick={(e) => {
if (e.ctrlKey || e.metaKey) {
selectedItems.includes(index)
? selectedItems.splice(selectedItems.indexOf(index), 1)
: selectedItems.push(index);
setSelectedItems(selectedItems);
} else {
setSelectedItems([]);
}
}}
/>
);
};
return (
<>
<h3>"CNTRL + Click" to select multiple items</h3>
<Table
pagination={false}
dataSource={dataSource}
columns={getColumns()}
rowKey="index"
components={{
body: {
wrapper: DraggableContainer,
row: DraggableBodyRow
}
}}
/>
{selectedItems.length ? <>{selectedItems.length} items selected </> : ""}
</>
);
}
You can play with it in Sandbox

Cannot Hook Category Name, and return the else statement

I made a function getCategoryNameById to get and match the id of the product and I pass the function as props in the other component to use it but when it's render a else statement which is a "none" string.
Example Data
Product Dummy Data
{
id: 4,
name: "ByProgrammers Sushi",
rating: 4.9,
categories: [1],
priceRating: expensive,
photo: images.japanese_restaurant,
duration: "10 - 15 min",
location: {
latitude: 1.5578068150528928,
longitude: 110.35482523764315,
},
courier: {
avatar: images.avatar_4,
name: "Ahmad"
},
menu: [
{
menuId: 9,
name: "Sushi sets",
photo: images.sushi,
description: "Fresh salmon, sushi rice, fresh juicy avocado",
calories: 100,
price: 50
}
]
},
Dummy Category Data
const categoryData = [
{
id: 1,
name: "Rice",
icon: icons.rice_bowl,
},
The State
const [categories, setCategories] = useState(categoryData)
const [selectedCategory, setSelectedCategory] = useState(null)
const [restaurants, setRestaurants] = useState(restaurantData)
const [currentLocation, setCurrentLocation] = useState(initialCurrentLocation)
The Function
function getCategoryNameById(id) {
let category = categories.filter(a => a.id == id)
if(category.length > 0)
return category[0].name
return "none"
}
Home Component
return (
<HomeComponentContext.Provider value={{
selectedCategory
}}>
<SafeAreaView>
<Top name={currentLocation.streetName}/>
<Categories
item={categories}
funct={onSelectedCategory}
selectcat={selectedCategory}
/>
<Product
products={restaurants}
function={getCategoryNameById}
cate = {categories}
/>
</SafeAreaView>
</HomeComponentContext.Provider>
)
the Usage of the Function in the Product Component
{
props.cate.map((categoryId) => {
return(
<View
key={categoryId}
style={{
flexDirection:'row'
}}
>
<Text style={{ ...FONTS.body3 }}>
{props.function(categoryId)}
</Text>
<Text>.</Text>
</View>
)
})
}

Why is the map undefined?

I am a novice at redux and i am trying to incorporate it in my code so the state can be managed more easily. I am trying to map through an array in my state but it is throwing the error below:
Uncaught TypeError: Cannot read property 'map' of undefined
this is the reducer for redux
const initialState = {
workoutlist: [
{
id: uuid.v4(),
name: 'Leg Day',
date: '08-09-2019',
duration: "60",
exerciselist: [
{
id: uuid.v4(),
exerciseName: 'Squats',
numberOfSets: "3",
reps: "12",
weight: "135",
},
{
id: uuid.v4(),
exerciseName: 'Leg press',
numberOfSets: "3",
reps: "10",
weight: "150",
},
{
id: uuid.v4(),
exerciseName: 'Lunges',
numberOfSets: "4",
reps: "12",
weight: "0",
},
],
selected: false,
},
{
id: uuid.v4(),
name: 'Running',
date: '08-11-2019',
duration: "40",
exerciselist: [],
selected: false,
},
],
disabled: true,
page: 1,
}
const workoutList = (state = initialState, action) => {
switch(action.type) {
// Returns whether the panel is selected or not
// and enables Start Workout button if only 1 is selected
case 'SELECT_PANEL':
state = {
workoutlist: state.workoutlist.map(workout => {
if (workout.id === action.id) {
workout.selected = !workout.selected
}
return workout;
})
}
var count = 0;
state.workoutlist.map((workout) => {
if (workout.selected === true) {
count = count + 1;
}
return count;
})
if (count !== 1) {
state = {
...state,
disabled: true
}
} else {
state = {
...state,
disabled: false
}
}
return state;
default:
return state;
}
}
this is the component that where the error is being thrown.
export default function WorkoutItem() {
const handleSelectedPanel = useSelector(state => state.workoutList);
const dispatch = useDispatch();
const { name, date, duration, exerciselist } = handleSelectedPanel;
return (
<ExpansionPanel style={styles.panel} onChange={() => dispatch(selectPanel())}>
<ExpansionPanelSummary>
<Typography variant="button" style={styles.header}>
{name}
</Typography>
<Typography variant="button" style={styles.header}>
{date}
</Typography>
<Typography align="right" style={styles.header}>
~{duration} mins
</Typography>
</ExpansionPanelSummary>
<ExpansionPanelDetails>
<Table size="medium" style={styles.table}>
<TableHead>
<TableRow>
<TableCell padding="none" >Name</TableCell>
<TableCell padding="none" align="right"># of sets</TableCell>
<TableCell padding="none" align="right">average reps</TableCell>
<TableCell padding="none" align="right">weight</TableCell>
</TableRow>
</TableHead>
<TableBody>
{exerciselist.map((exercise) => (
<ExerciseList
key={exercise.id}
exercise={exercise}
/>
))}
</TableBody>
</Table>
<ExpansionPanelActions disableSpacing style={styles.actionButton}>
<EditWorkoutItem
workout={this.props.workout}
handleEditChange={this.props.handleEditChange}
/>
</ExpansionPanelActions>
</ExpansionPanelDetails>
</ExpansionPanel>
)
}
It is supposed to show a list of panels that can be expanded to show the contents but it throws an error saying the exerciselist is undefined in my state apparently.
Any help would be greatly appreciated!
Do you want to access the first item or workoutList ?. From your code handleSelectedPanel seams to be an array not an object. Is your destructuring correct?. Where is your useSelector?. What does console.log(handleSelectedPanel) gives you? Try
const { name, date, duration, exerciselist } = handleSelectedPanel[0];
or
const handleSelectedPanel = useSelector(state => state.workoutList[0]);

Categories

Resources