Material UI 5 Indeterminate checkbox doesn't work properly - javascript

I'm trying to add more children to the parent checkbox in the FormControlLabel.
Everything is working properly, however, the third child doesn't work properly. I want it to work as the Material UI Example
Here is my code
import * as React from "react";
import Box from "#mui/material/Box";
import Checkbox from "#mui/material/Checkbox";
import FormControlLabel from "#mui/material/FormControlLabel";
export default function IndeterminateCheckbox() {
const [checked, setChecked] = React.useState([true, false, false]);
const handleChange1 = (event) => {
setChecked([
event.target.checked,
event.target.checked,
event.target.checked
]);
};
const handleChange2 = (event) => {
setChecked([event.target.checked, checked[1], checked[2]]);
console.log(checked, "first");
};
const handleChange3 = (event) => {
setChecked([checked[0], event.target.checked, checked[2]]);
console.log(checked, "second");
};
const handleChange4 = (event) => {
setChecked([checked[0], event.target.checked, checked[1]]);
console.log(checked, "third");
};
const children = (
<Box sx={{ display: "flex", flexDirection: "column", ml: 3 }}>
<FormControlLabel
label="Child 1"
control={<Checkbox checked={checked[0]} onChange={handleChange2} />}
/>
<FormControlLabel
label="Child 2"
control={<Checkbox checked={checked[1]} onChange={handleChange3} />}
/>
<FormControlLabel
label="Child 3"
control={<Checkbox checked={checked[2]} onChange={handleChange4} />}
/>
</Box>
);
return (
<div>
<FormControlLabel
label="Parent"
control={
<Checkbox
checked={checked[0] && checked[1] && checked[2]}
indeterminate={checked[0] !== checked[1] && checked[2]}
onChange={handleChange1}
/>
}
/>
{children}
</div>
);
}
Any advice would be greatly appreciated, I am new to Material UI and react so please excuse any syntax problems.
Thank you!

Related

How to Style label on MUI Radio Button when checked

Good day everyone I'm trying to style the label text on the radio button to change to a blue color when selected.
THIS IS MY CODE OF THE MUI BUTTON SO FAR
import * as React from "react";
import Radio from "#mui/material/Radio";
import RadioGroup from "#mui/material/RadioGroup";
import FormControlLabel from "#mui/material/FormControlLabel";
import FormControl from "#mui/material/FormControl";
export default function RowRadioButtonsGroup({label1, label2}) {
return (
<FormControl>
<RadioGroup
row
aria-labelledby="demo-row-radio-buttons-group-label"
name="row-radio-buttons-group"
style={{display: 'flex', gap: '2rem'}}
sx={{
'& .MuiSvgIcon-root': {
fontSize: 28,
},
}}
>
<FormControlLabel value="Sunday" control={<Radio />} label={label1}/>
<FormControlLabel value="Monday" control={<Radio />} label={label2} />
</RadioGroup>
</FormControl>
);
}
Basically just create a styled form control label and use "useRadioGroup " hook button and choose the colors for checked and unchecked
https://codesandbox.io/s/radiobuttonsgroup-demo-material-ui-forked-pix9rg?file=/demo.js
// Custom label
const StyledFormControlLabel = styled((props) => (
<FormControlLabel {...props} />
))(({ theme, checked }) => ({
".MuiFormControlLabel-label": checked && {
// Change color here
color: "red"
}
}));
// Custom FormControl
function MyFormControlLabel(props) {
// MUI UseRadio Group
const radioGroup = useRadioGroup();
let checked = false;
if (radioGroup) {
checked = radioGroup.value === props.value;
}
return <StyledFormControlLabel checked={checked} {...props} />;
}
<MyFormControlLabel value="female" control={<Radio />} label="Female" />

React - Secondary Prop Value - Node - Material UI

I've been working on simplifying my code and am curious how I would approach passing a secondary value using props and fetching data from the back end. I'm using material UI's Autocomplete and the PERN stack. Everything is working, except I want to change "region_name" to be a prop. So I can change the values dynamically within event details.js. when I'm fetching other data.
I currently have this component setup.
Production.js
import Autocomplete from "#mui/material/Autocomplete";
import Box from "#mui/material/Box";
import Stack from "#mui/material/Stack";
import TextField from "#mui/material/TextField";
export default function CustomAutoComplete(props) {
return (
<Stack sx={{ m: 1 }}>
<Autocomplete
sx={{ ml: 2, mr: 2 }}
size="small"
id="combo-box-demo"
freeSolo
inputValue={props.inputValue}
onInputChange={(event, newValue) => {
props.set(newValue);
}}
getOptionLabel={(data) => `${data.region_name}`}
options={props.data}
isOptionEqualToValue={(option, value) =>
option.region_name === value.region_name
}
renderOption={(props, data) => (
<Box component="li" {...props} key={data.id}>
{data.region_name}
</Box>
)}
renderInput={(params) => <TextField {...params} label="Region" />}
/>
</Stack>
);
}
Then importing it into a separate file EventDetails.js fetching the data and storing it in LocalStorage, which I'll move to useState eventually.
import CustomAutoComplete from "../../atoms/AutoComplete";
import FormGroup from "#mui/material/FormGroup";
import { Fragment, useState, useEffect } from "react";
import { useLocalStorage } from "../../utils/LocalStorage.js";
const EventDetails = () => {
const [region, setRegion] = useLocalStorage("region", "");
const [getRegion, setGetRegion] = useState([]);
// fetching backend data
useEffect(() => {
fetch("/authentication/region")
.then((response) => response.json())
.then((getRegion) => setGetRegion(getRegion));
}, []);
return (
<Fragment>
<FormGroup sx={{ p: 2, m: 1 }}>
<CustomAutoComplete
inputValue={region}
set={setRegion}
data={getRegion}
key={getRegion.id}
name={region_name} // <--feeble attempt
label="Region"
/>
</FormGroup>
</Fragment>
);
};
I had someone help me with finding a solution just had to create a prop variable like
export default function CustomAutoComplete(props) {
const { labelValue } = props;
return (renderOption={(props, data) => (
<Box component="li" {...props} key={data.id}>
{data[labelKey]}
</Box>
)})
then in the parent component
<CustomAutoComplete labelValue="region_name" />

Multilevel drop downs with checkboxes in React

I want to create nested dropdowns with each having checkboxes in them like this:
Is there a way to do this in react. Couldn't find a way to implement this with any specific library
You can create a nested dropdown with checkboxes with material ui
Here's the link you can view:
https://mui.com/components/checkboxes/
And here's the source code from material UI to achieve the result:
import * as React from 'react';
import Box from '#mui/material/Box';
import Checkbox from '#mui/material/Checkbox';
import FormControlLabel from '#mui/material/FormControlLabel';
export default function IndeterminateCheckbox() {
const [checked, setChecked] = React.useState([true, false]);
const handleChange1 = (event) => {
setChecked([event.target.checked, event.target.checked]);
};
const handleChange2 = (event) => {
setChecked([event.target.checked, checked[1]]);
};
const handleChange3 = (event) => {
setChecked([checked[0], event.target.checked]);
};
const children = (
<Box sx={{ display: 'flex', flexDirection: 'column', ml: 3 }}>
<FormControlLabel
label="Child 1"
control={<Checkbox checked={checked[0]} onChange={handleChange2} />}
/>
<FormControlLabel
label="Child 2"
control={<Checkbox checked={checked[1]} onChange={handleChange3} />}
/>
</Box>
);
return (
<div>
<FormControlLabel
label="Parent"
control={
<Checkbox
checked={checked[0] && checked[1]}
indeterminate={checked[0] !== checked[1]}
onChange={handleChange1}
/>
}
/>
{children}
</div>
);
}
Here's the codesandbox link where I have combined the material UI component with the checkboxes.
https://codesandbox.io/s/indeterminatecheckbox-material-demo-forked-o0vvw?file=/demo.js:0-2222

Styling a card causes TextField to lose focus in Material UI + React

I'm trying to style my card so that it's not so big but the problem is every time I do that, my TextField loses its' functionality and I have to keep on clicking on the TextField because it keeps on losing focus. I need to make my Card component smaller without losing the functionality of my TextField.
https://codesandbox.io/s/mutable-monad-dsvf8?file=/src/index.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import Grid from "#material-ui/core/Grid";
import Button from "#material-ui/core/Button";
import Card from "#material-ui/core/Card";
import TextField from "#material-ui/core/TextField";
import CreateIcon from "#material-ui/icons/Create";
import Box from "#material-ui/core/Box";
import CardMedia from "#material-ui/core/CardMedia";
import MuiAlert from "#material-ui/lab/Alert";
import Snackbar from "#material-ui/core/Snackbar";
import { withStyles } from "#material-ui/core/styles";
const PetitionCard = () => {
const StyledCard = withStyles({
root: { height: 450, width: 350 }
})(Card);
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [open, setOpen] = useState(false);
const [petition, newPetition] = useState(false);
const handleTitleChange = event => {
setTitle(event.target.value);
};
const handleDescriptionChange = event => setDescription(event.target.value);
const handleClose = (event, reason) => {
if (reason === "clickaway") {
return;
}
};
const Alert = props => <MuiAlert elevation={6} variant="filled" {...props} />;
const Message = (message, severity) => {
return (
<Snackbar open={!open} autoHideDuration={3000} onClose={handleClose}>
<Alert severity={severity}>{message}</Alert>
</Snackbar>
);
};
const clearField = event => {
setOpen(true);
if (title.length > 0 && description.length > 0) {
setTitle("");
setDescription("");
return (
<Message
open={open}
message={"You have successfully created a petition!"}
severity={"success"}
/>
);
} else {
return (
<Message
message={"You have one more more fields missing"}
severity={"error"}
/>
);
}
};
return (
<StyledCard>
<Box mt={1}>
<Grid container justify="center">
<TextField
id="outlined-multiline-static"
multiline
rows={1}
variant="outlined"
placeholder="Title"
value={title}
onChange={handleTitleChange}
/>
</Grid>
</Box>
<CardMedia title="Petition" style={{ height: 0, paddingTop: "40.25%" }} />
<Box mt={1} justify="center">
<Grid container justify="center">
<TextField
size="small"
inputProps={{
style: { fontSize: 15 }
}}
id="outlined-multiline-static"
multiline
rows={5}
placeholder="Description"
variant="outlined"
value={description}
onChange={handleDescriptionChange}
/>
</Grid>
</Box>
<Box mt={1}>
<Grid container justify="center">
<Button onClick={clearField}>
<CreateIcon />
Create Petition!
</Button>
</Grid>
</Box>
</StyledCard>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<PetitionCard />
</React.StrictMode>,
rootElement
);
The problem is that you are re-creating StyledCard whenever PetitionCard is rendered:
const PetitionCard = () => {
const StyledCard = withStyles({
root: { height: 450, width: 350 }
})(Card);
[...]
}
Therefore, a new TextField is created on every render since its container changes. TextField is by default not focused and doesn't know whether the TextField from the previous render was focused.
The solution is to create StyledCard outside PetitionCard:
const StyledCard = withStyles({
root: { height: 450, width: 350 }
})(Card);
const PetitionCard = () => {
[...]
}

How to create checkbox in A React Function

I am trying to create a Checkbox to display and hide my React Table with some data in it. I have only used classes and am new to using Functions and as a result am struggling to implement a way to create a checkbox that can hide my React Table or a column.
import "react-table/react-table.css";
import React, { Component, useState, useEffect } from "react";
function dataquery() {
return fetch("www.website.com").then(response =>
response.json()
);
}
function Offence() {
const [count, setCount] = useState([]);
useEffect(() => {
dataquery().then(headlines => {
setCount(headlines);
});
}, []);
//event.preventDefault();
console.log(count.offences);
let data = [{}];
if (typeof count.offences !== "undefined" ) {
let newdata = count.offences.map(count => data.push({ name: count }));
// console.log("???");
}
console.log(typeof count.offence);
const columns = [
{
Header: "Name",
accessor: "name",
},
];
// trying to hide this react table or just hide the column
return <ReactTable data={data} columns={columns} filterable />;
}
export default Offence;
I am exporting this function into another file in which I render 'Offence'.
The fetch website is not the actual website as it needs a private login to work, so I replaced it with this placeholder for the purpose of this.
Thank you.
You can easily add an useState hook, which stores a boolean to show/not show the table. Then toggle this state when changing a checkbox. For example:
function Offence() {
// ... your component code
const [showTable, setShowTable] = useState(true);
// output
return (
<>
<input
type="checkbox"
checked={showTable}
onChange={() => { setShowTable(p => !p); }}
/>
{showTable ? <ReactTable ... /> : null}
</>
);
}
I have only used classes and am new to using Functions
In such a situation, I highly recommend to use materialui components. It would make your life much easier because you need not to step into gory details of styling anymore if you do not want to.
Below I roughly drafted a component which contains a table and a list of checkboxes for switching hide/show columns.
Hope it helps :)
import React, { useState, useEffect } from 'react'
import Grid from '#material-ui/core/Grid';
import Card from '#material-ui/core/Card';
import CardHeader from '#material-ui/core/CardHeader';
import CardContent from '#material-ui/core/CardContent';
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import FormControl from '#material-ui/core/FormControl';
import FormGroup from '#material-ui/core/FormGroup';
import FormControlLabel from '#material-ui/core/FormControlLabel'
import Checkbox from '#material-ui/core/Checkbox';
function App() {
const [showName, setshowName] = useState(true);
const [showQty, setshowQty] = useState(true);
const [showPrice, setshowPrice] = useState(true);
const dummydata = [{ name: "apple", qty: 12, price: 3.3 }, { name: "orange", qty: 3, price: 1.5 }, { name: "grape", qty: 10, price: 4.3 }]
return (
<Grid
container
direction="row"
justify="space-around"
alignItems="center"
>
<Grid item xs={12} sm={5}>
<Card>
<Table>
<TableHead>
<TableRow>
{showName ? <TableCell>Name</TableCell> : ""}
{showQty ? <TableCell >Qty.</TableCell> : ""}
{showPrice ? <TableCell >Price</TableCell> : ""}
</TableRow>
</TableHead>
<TableBody>
{dummydata.map(item => (
<TableRow>
{showName ? <TableCell component="th" scope="row" padding="none">
{item.name}
</TableCell> : ""}
{showQty ? <TableCell>{item.qty}</TableCell> : ""}
{showPrice ? <TableCell>{item.price}</TableCell> : ""}
</TableRow>
))}
</TableBody>
</Table>
</Card>
</Grid>
<Grid item xs={12} sm={5}>
<Card>
<CardHeader
title="Hide any column?"
/>
<CardContent>
<FormControl style={{ margin: 4 }}>
<FormGroup>
<FormControlLabel
control={
<Checkbox onChange={(e, checked) => setshowName(checked)} checked={showName} />
}
label="Hide Name"
/>
<FormControlLabel
control={
<Checkbox onChange={(e, checked) => setshowQty(checked)} checked={showQty} />
}
label="Hide Quantity"
/>
<FormControlLabel
control={
<Checkbox onChange={(e, checked) => setshowPrice(checked)} checked={showPrice} />
}
label="Hide Price"
/>
</FormGroup>
</FormControl>
</CardContent>
</Card>
</Grid>
</Grid>
);
}
export default App;

Categories