Material-UI formControlLabel whole label is clickable only text should be - javascript

I am new to the material UI. here I have the following form
<FormControl
variant="outlined"
className={css.formControl}
margin="dense"
key={"abc_" + index}
>
<FormControlLabel
control={
<Checkbox
onClick={handleClick(data)}
checked={_.some(selected, { Id: selected.Id })}
value={selected.Id}
color="default"
/>
}
label={data?.Name ?? "NO_LABEL"}
/>
</FormControl>
Now, this whole label gets clickable as the area is a bit long, so, what I am trying is the only the checkbox and the text should be clickable and the other empty space should not be clicked. Here , I have given the
max-width for that label to be 272px.
How do I add that?
Thanks.

You can prevent parent elements from click events, as well as allow the child to do it.
Use pointer-events to disable click event.
pointer-events: none;
<FormControlLabel
style={{ pointerEvents: "none" }}
control={
<Checkbox
onClick={handleClick}
style={{ pointerEvents: "auto" }}
color="default"
/>
}
label={"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
/>

I had the same problem with those checkboxes, see here:
With dev tools:
The label takes whole space (purple space).
That is due to the FormGroup displaying children in a column flex container.
To fix it, in my custom overloaded checkbox, I used:
import * as React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import FormGroup from '#material-ui/core/FormGroup';
import MUICheckbox from '#material-ui/core/Checkbox';
const useFormGroupStyles = makeStyles({
root: {
display: 'block',
},
});
const Checkbox = (props) => {
const { onCheck } = props;
const formGroupClasses = useFormGroupStyles();
const checkbox = (
<MUICheckbox
onChange={event => onCheck(event, event.target.checked)}
icon={props.uncheckedIcon}
checkedIcon={props.checkedIcon}
color="primary"
style={props.style}
/>
);
return (
<FormGroup classes={formGroupClasses}>
<FormControlLabel
control={checkbox}
label={props.label}
style={props.style}
/>
</FormGroup>
);
};
export default Checkbox;

This will do
MuiFormControlLabel: {
styleOverrides: {
root: {
width: "fit-content"
}
}
}

Related

React <Switch> is not getting updated or changing its state

Hey guys I am learning react and have a form to edit book details. I am using django in the backend. I am not able to update the e-book which is a switch to turn on and off according to whether e-book is available or not. The switch works fine, but no data is being changed in the database. I am confused on how to work with the switch and saw lots of resources saying different things which is quite difficult to understand. Rest of the fields are getting updated correctly. Can someone tell me what changes I have to make in this switch to make it work??
code
import React, {useEffect, useState} from 'react'
import axiosInstance from '../../axios';
import { useForm, Controller } from 'react-hook-form';
//MaterialUI
import Button from '#material-ui/core/Button';
import CssBaseline from '#material-ui/core/CssBaseline';
import TextField from '#material-ui/core/TextField';
import Grid from '#material-ui/core/Grid';
import Typography from '#material-ui/core/Typography';
import { makeStyles } from '#material-ui/core/styles';
import Container from '#material-ui/core/Container';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Switch from '#material-ui/core/Switch';
import Select from '#material-ui/core/Select';
import InputLabel from '#material-ui/core/InputLabel';
import MenuItem from '#material-ui/core/MenuItem';
import FormControl from '#material-ui/core/FormControl';
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
bookformbody: {
display: "flex",
backgroundColor: "#ffff",
height: "100vh",
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(3),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
function BookEdit() {
const initialFormData = Object.freeze({
id: '',
summary: '',
published_date: '',
e_book: false,
});
const [formData, updateFormData] = useState(initialFormData);
useEffect(() => {
axiosInstance.get('api/books/details/view/').then((res) => {
updateFormData({
...formData,
['summary']: res.data.summary,
['published_date']: res.data.published_date,
['e_book']: res.data.e_book,
});
console.log(res.data);
});
}, [updateFormData]);
const handleChange = (e) => {
if(e.target.name === "e_book"){
return(
updateFormData({
...formData,
[e.target.name]: e.target.checked
})
)
}
updateFormData({
...formData,
// Trimming any whitespace
[e.target.name]: e.target.value
});
};
const onSubmit = (data) =>{
let formData = new FormData();
formData.append('summary', data.summary);
formData.append('published_date', data.published_date);
formData.append('e_book', data.e_book);
axiosInstance.put('api/books/details/edit/', formData);
} ;
const classes = useStyles();
const { register, handleSubmit, control, errors } = useForm();
return (
<>
<Header />
<div className={classes.bookformbody}>
<SideBar />
<Container component="main" maxWidth="sm">
<CssBaseline />
<div className={classes.paper}>
<Typography component="h1" variant="h5">
Edit Book Details
</Typography>
<form className={classes.form} noValidate onSubmit={handleSubmit(onSubmit)}>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
id="summary"
label="Book Summary"
name="summary"
autoComplete="summary"
value={formData.summary}
onChange={handleChange}
inputRef={register({maxLength: 1000})}
multiline
rows={4}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
type="date"
label="Published Date"
name="published_date"
autoComplete="published_date"
value={formData.published_date}
onChange={handleChange}
inputRef={register({required: true})}
InputLabelProps={{
shrink: true,
}}
/>
</Grid>
<Grid item xs={12}>
<InputLabel id="e-book-switch">E-Book</InputLabel>
<Controller
name="e_book"
control={control}
as={
<Switch size="small"
id="e-book-switch"
type="checkbox"
name="e_book"
onChange={handleChange}
// inputRef={register}
value={formData.e_book}
checked={formData.e_book}
/>
}
/>
</Grid>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Update
</Button>
</form>
</div>
</Container>
</div>
</>
)
}
export default BookEdit;
You are passing props to Switch directly, but what you should do is to use Controller props, and Controller will then pass it down to Switch:
<Controller as={Switch} value={formData.e_book} ... />
Otherwise you need to use render, not as
This is actually described pretty good here:
https://react-hook-form.com/api/#Controller
UPDATE
Here is the sandbox where it is working fine with above changes - https://codesandbox.io/s/kind-nash-s94v0
What i did there is simply this:
<Controller
name="e_book"
control={control}
render={(props) => {
return (
<Switch
size="small"
id="e-book-switch"
type="checkbox"
name="e_book"
onChange={handleChange}
// inputRef={register}
value={formData.e_book}
checked={formData.e_book}
/>
);
}}
/>
You are initializing the value as a string at the beginning of BookEdit(). Try to set initialFormData like this:
const initialFormData = Object.freeze({
id: '',
summary: '',
published_date: '',
e_book: false,
});

How to customize the font size of an active tab in material-ui

My Requirement is such that only the active tab should have a specific color and font-size.
This is my code:
<Tabs
value={value}
onChange={handleChange}
classes={{indicator: classes.customStyleOnActiveTab}}
aria-label="some text"
>
<Tab label={<span className={classes.customStyleOnTab}>Tab 1</span>} />
<Tab label={<span className={classes.customStyleOnTab}> Tab 2</span>}/>
</Tabs>
However, it changes the styling on both the tabs whereas I want only the active tab to have a particular style (blue color and bold font). The other tab should have a normal font-weight and color:
If I use textColor property, I can achieve the desired result but I wouldn't be able to customize it. I dug into the material doc, and eventually tried all the CSS classes they've exposed, without any luck
For adding custom/different style to the active tab you can assign a class to the active tab conditionally. Every Tab has its own value (which is their index value also) and assign them class conditionally.
Here is the link of codesandbox:- https://codesandbox.io/s/elegant-tu-lxi1g?file=/src/App.js
import React, { useState } from "react";
import "./styles.css";
import {Tabs, Tab, makeStyles} from '#material-ui/core'
export default function App() {
const classes = useStyles()
const [value, setValue] = useState(0)
const handleChange = (e, newVal)=>{
setValue(newVal)
}
return (
<div className="App">
<Tabs
value={value}
onChange={handleChange}
classes={{indicator: classes.customStyleOnActiveTab}}
aria-label="some text"
>
<Tab label={<span className={ value === 0 ? classes.activeTab : classes.customStyleOnTab}>Tab 1</span>} />
<Tab label={<span className={ value === 1 ? classes.activeTab : classes.customStyleOnTab}> Tab 2</span>}/>
</Tabs>
</div>
);
}
const useStyles = makeStyles({
customStyleOnTab:{
fontSize:'15px',
color:'green'
},
customStyleOnActiveTab:{
color:'red'
},
activeTab:{
fontSize:'16px',
fontWeight:'600',
color:'pink'
}
})
also, you can assign the className to the Tab element instead of span for keeping the label prop clean, tidy, and uniform.
You can change by use makeStyle.
const useStyle = makeStyles((theme) => ({
tab: {
"& .Mui-selected": {
color: "red",
fontSize: "20px"
}
}
})
then
<Tabs
className={classes.tab}
>
<Tab label="Teacher Information" />
<Tab label="Contract" />
</Tabs>
Another possible solution is to use withStyles.
...
import { default as MuiTab } from "#material-ui/core/Tab";
import { withStyles } from "#material-ui/core/styles";
const styles = {
// check https://material-ui.com/api/tab/#css
// for more overridable styles
selected: {
fontSize: "16px",
fontWeight: "600",
color: "pink"
}
};
const Tab = withStyles(styles)((props) => <MuiTab {...props} />);
function App() {
const [value, setValue] = React.useState(0);
const handleChange = (e, newVal) => {
setValue(newVal);
};
return (
<div className="App">
<Tabs value={value} onChange={handleChange}>
<Tab label="Tab 1" />
<Tab label="Tab 2" />
</Tabs>
</div>
);
}

Nested MaterialUI Tabs throws an error when opening second tabs level

I am trying to build a nested horizontal tabs in MaterialUI, I mean, a first tabs level that, when you click on it, open a second tabs level.
Here is a link to the working replicable code example: https://codesandbox.io/s/sweet-pasteur-x4m8z?file=/src/App.js
The problem is: When I click on first level, second level is opened, when I click on a item from second level, I get this error
Material-UI: the value provided to the Tabs component is invalid.
None of the Tabs' children match with "value21".
You can provide one of the following values: value11
For replicate the error, you could do next steps:
Click in "Label 1"
Click in "Label 1.1"
Error is thrown
I do not understand why that error, if I am splitting values of each tab in different states and, supposedly, it is all Ok. Maybe the way I use for implementing the nested tab is wrong, any idea what could be happening?
Thank you.
I created three tab components, one parent and two children. Then I Imported the children tab components into the parent. You can use vertical tabs for the child tab components to help with the layout. check out the how the parent tab looks like. Note all these are tab components
// Parent tab component
import React from 'react';
import PropTypes from 'prop-types';
import SwipeableViews from 'react-swipeable-views';
import { makeStyles, useTheme } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Tabs from '#material-ui/core/Tabs';
import Tab from '#material-ui/core/Tab';
import Typography from '#material-ui/core/Typography';
import Box from '#material-ui/core/Box';
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`full-width-tabpanel-${index}`}
aria-labelledby={`full-width-tab-${index}`}
{...other}
>
{value === index && (
<Box p={3}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.any.isRequired,
value: PropTypes.any.isRequired,
};
function a11yProps(index) {
return {
id: `full-width-tab-${index}`,
'aria-controls': `full-width-tabpanel-${index}`,
};
}
const useStyles = makeStyles((theme) => ({
root: {
backgroundColor: theme.palette.background.paper,
width: 500,
},
}));
export default function FullWidthTabs() {
const classes = useStyles();
const theme = useTheme();
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
const handleChangeIndex = (index) => {
setValue(index);
};
return (
<div className={classes.root}>
<AppBar position="static" color="default">
<Tabs
value={value}
onChange={handleChange}
indicatorColor="primary"
textColor="primary"
variant="fullWidth"
aria-label="full width tabs example"
>
<Tab label="Item One" {...a11yProps(0)} />
<Tab label="Item Two" {...a11yProps(1)} />
</Tabs>
</AppBar>
<SwipeableViews
axis={theme.direction === 'rtl' ? 'x-reverse' : 'x'}
index={value}
onChangeIndex={handleChangeIndex}
>
<TabPanel value={value} index={0} dir={theme.direction}>
<ChildTabOne/>
</TabPanel>
<TabPanel value={value} index={1} dir={theme.direction}>
<ChildTabTwo/>
</TabPanel>
</SwipeableViews>
</div>
);
}

How to change material-ui Textfield label styles in react

I'm new to Material-UI, I couldn't able to figure it out, how to change the color of the label which is showing in grey color. I want it in black. Can anyone help me with this query?
Here is the Code :
import React from "react";
import ReactDOM from "react-dom";
import { TextField, Button, Grid } from "#material-ui/core";
class App extends React.Component {
render() {
return (
<Grid container justify={"center"} alignItems={"center"} spacing={1}>
<Grid item>
<TextField
id="outlined-name"
label="Name"
value={"Enter value"}
onChange={() => console.log("I was changed")}
margin="normal"
variant="outlined"
/>
</Grid>
<Grid item>
<Button variant="contained" color="primary">
Submit
</Button>
</Grid>
</Grid>
);
}
}
Here is the code: "https://codesandbox.io/s/fancy-morning-30owz"
If you use the selection tools in your browser, you would find out that:
The class name used is MuiFormLabel-root
<label class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled" data-shrink="true" for="outlined-name">Name</label>
So set the styles using nesting selector to the TextField component
Functional component
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: {
"& .MuiFormLabel-root": {
color: "red" // or black
}
}
}));
...
const classes = useStyles();
Classical component
import { withStyles, createStyles } from "#material-ui/core/styles";
const styles = theme => createStyles({
root: {
"& .MuiFormLabel-root": {
color: "red"
}
}
});
...
const { classes } = this.props;
...
export default withStyles(styles)(App);
usage
<TextField
className={classes.root}
...
>
</TextField>
By this way, you can change the label color, as the screenshot is shown below (currently red)
Try it online:
If you want to leave your style in a separate file, you can write:
.MuiTextField-root > label {
background-color: $bg-color;
color: $color;
}
.MuiTextField-root > .MuiFormLabel-root.Mui-focused {
color: $color;
}

material ui change the checkbox color

I am trying to change the color of the checkboxes and radio button.
so I did a research and got this link. Material UI change Input's active color
but still I am getting the error. (0 , _styles2.createMuiTheme) is not a function
can you tell me how to change the checkbox colors so that I can use it other places
https://codesandbox.io/s/m7z2l1j09y
const theme = createMuiTheme({
palette: {
secondary: {
main: "#E33E7F"
},
formControl: {
color: "black"
}
}
});
<MuiThemeProvider theme={theme}>
<FormControl component="fieldset" className={classes.formControl}>
<FormLabel component="legend">Gender</FormLabel>
<RadioGroup
aria-label="Gender"
name="gender1"
className={classes.group}
value={this.state.value}
onChange={this.handleChange}
>
{radioValues.map(radio => {
return (
<FormControlLabel
value={radio.value}
control={<Radio />}
label={radio.label}
/>
);
})}
</RadioGroup>
{checkBoxvalues.map((check, index) => {
return (
<FormControlLabel
key={check.value}
control={
<Checkbox
checked={check.checked}
onChange={this.handleCheckBoxChange(check.value, index)}
value={check.value}
/>
}
label={check.label}
/>
);
})}
</FormControl>
</MuiThemeProvider>
Your error was due to the import being incorrect.
Instead of
import { MuiThemeProvider, createMuiTheme } from "material-ui/styles";
It should be
import { MuiThemeProvider, createMuiTheme } from "#material-ui/core/styles";
I also added specifying the color property on the Checkbox.
Here's a working version of your sandbox: https://codesandbox.io/s/w68nm77o0k

Categories

Resources