Material-UI checkboxes and radio buttons look so ugly - checkbox

Hi! I was making a form using Formik in React (class-based component) and I got very ugly looking checkboxes and radio buttons. I have tried to dig-into the code using inspect element in Chrome, but still couldn't solve it. I have uploaded here the picture as well. I have used the same checkboxes in Angular from the same source, but works fine there. I don't know why it is not working in React.
The Material-UI is installed in package.json file as a dependency:
"#material-ui/core": "^4.11.0"
Here is how I have written the code:
import React, { Component } from 'react';
import { Formik } from 'formik';
import { FormControlLabel, FormControl, FormLabel, Checkbox, Select, MenuItem, Radio, RadioGroup } from '#material-ui/core';
export default class FormikForm extends Component {
componentDidMount() {}
render() {
return (
<div className="formik-container">
<Formik>
<form>
<FormControlLabel
className="paper-checkbox col-md-12"
control={
<Checkbox
onChange={handleChange}
onBlur={handleBlur}
value="markAllDay"
color="secondary"
name="markAllDay"
/>
}
label="Book for the whole day"
/>
<FormControlLabel
className="paper-checkbox col-md-12"
control={
<Checkbox
onChange={handleChange}
onBlur={handleBlur}
value="markRecurring"
color="secondary"
name="markRecurring"
/>
}
label="Recurring event"
/>
<FormControl component="fieldset">
<RadioGroup
row aria-label="eventType"
name="recurEventType"
onChange={handleChange}
>
<FormControlLabel
value="recur"
control={<Radio />}
label="Whole recur event"
/>
<FormControlLabel
value="event"
control={<Radio />}
label="Only this event"
/>
</RadioGroup>
</FormControl>
</form>
</Formik>
</div>
);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Related

Remove the border from TexfField

I started using #Mui for React and I used it to create the form but after I focused TextField I see the border linke on the below screen:
My code look like this:
<FormGroup>
<TextField
label="Description"
name="description"
multiline
rows={5}
fullWidth
value={data.description}
variant="standard"
onChange={onHandleChange}
/>
</FormGroup>
How remove that?
#Edit
I resolved my problem. Border around of this element appears becouse I has styles from Breeze
Normally this can be done via CSS as well.
input {
outline: none
}
You can change the styling (remove the underline) of TextField when it is focused with makeStyles using :after
In your case do the following :
import TextField from "#mui/material/TextField";
import FormGroup from "#mui/material/FormGroup";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
underline: {
"&&:after": {
borderBottom: "none"
}
}
});
export default function ComboBox() {
const classes = useStyles();
return (
<FormGroup>
<TextField
InputProps={{ classes }}
label="Description"
name="description"
multiline
rows={5}
fullWidth
value={data.description}
variant="standard"
onChange={onHandleChange}
/>
</FormGroup>
);
}
And if you want it with no border at all you can pass InputProps={{ disableUnderline: true }} to your TextField

How to make smaller radio buttons

I can't find a way to create a group of three small (19px high) labelled radio buttons in material-ui. I'm migrating a browser app from static HTML/JS into material-ui/react, and I need the group to stay the same size.
The button group I'm starting with has three small vertically aligned labelled radio buttons. Here's
a screenshot:
Here's the code for the best I've been able to do using the material-ui documentation:
<FormControl
margin="dense"
size="small"
>
<RadioGroup
size="small"
name="dataSource"
value={dataSource}
onChange={handleDataSourceChange}
>
<FormControlLabel
value="CaseCount"
control={
<Radio
className={classes.radio}
size="small"
/>
}
label="Cases"
/>
<FormControlLabel
value="DeathCount"
control={
<Radio
className={classes.radio}
size="small"
/>
}
label="Deaths"
/>
<FormControlLabel
value="HotSpots"
control={
<Radio
size="small"
/>
}
label="HotSpot warning"
/>
</RadioGroup>
</FormControl>
This results in an oversized group -- the button icons are too large, the text is too large, and each row is 38 pixels high (twice the 19 pixels of the original). Here's a screenshot of the material-ui counterpart:
I think I want the result to use a vanilla html input (with type of radio) instead of an svg icon, and a font with font-height of 13px. How do I do that in material-ui?
I know how to fix the padding-left so I'm not worried about that. How do I get rows that are 19px high instead of 38px?
Reason
If you inspect the Material radio button, we can see that the padding of the radio button is causing each row to have a height of 38px.
Code
Therefore, we can simply remove the vertical padding from all radio buttons with the following code (note that my code is slightly different than yours):
const useStyles = makeStyles({
// Applied to <Radio />
root: {
width: 19,
height: 19,
paddingTop: 0,
paddingBottom: 0,
},
// Applied to <FormControlLabel />
label: {
fontSize: 13
}
});
export default function RadioButtonsGroup() {
const [value, setValue] = React.useState("CaseCount");
const classes = useStyles();
const handleChange = (event) => {
setValue(event.target.value);
};
const customRadio = <Radio size="small" classes={{root: classes.root}} />;
return (
<FormControl component="fieldset">
<RadioGroup value={value} onChange={handleChange}>
<FormControlLabel classes={{label: classes.label}} control={customRadio} value="CaseCount" label="Cases" />
<FormControlLabel classes={{label: classes.label}} control={customRadio} value="DeathCount" label="Deaths" />
<FormControlLabel
classes={{label: classes.label}}
control={customRadio}
value="HotSpots"
label="Hotspot Warning"
/>
</RadioGroup>
</FormControl>
);
}
Explanation
According to the Radio API documentation, we can apply custom styling to root of the radio button by overriding styles with classes using the class name of root. Therefore, we first define a style object called root in the makeStyles() function. Next, we apply the styling to the Radio component by adding the prop of classes={{root: classes.root}}:
<Radio size="small" classes={{root: classes.root}} />
Similarly, according to the FormControlLabel API documentation, we can apply custom styling to the text label using the label class name. Therefore, we first define a style object of label in the makeStyles() function. Next, we apply the styling to the FormControlLabel component by adding the prop of classes={{label: classes.label}}:
<FormControlLabel classes={{label: classes.label}} /* ... */ />

How to extend React DatePicker pop-up once it's triggered to show?

There is an annoying problem when I try to implement DatePicker form input in my simple frontend project. I've a page that displays a user form based on this code:
import React, { Component } from 'react';
import AppNavbar from './AppNavbar'
import DatePicker from 'react-datepicker'
import './App.css'
import { Container, FormGroup, Form, Button, Input, Label } from 'reactstrap'
import {Link} from 'react-router-dom'
class CostLog extends Component {
state = { }
render() {
return (
<div>
<AppNavbar />
<h2 style={{display: 'flex', justifyContent: 'center', alignItems: 'center', height: '50px'}}>Cost overview</h2>
<Container>
<Form>
<FormGroup>
<Label for='title'>Title</Label>
<Input className='input-cust' type='text' name='title' id='title' onChange={this.inputHandler} />
</FormGroup>
<FormGroup>
<Label for='title'>Category</Label>
<Input type='text' name='category' id='category' onChange={this.inputHandler} />
</FormGroup>
<FormGroup>
<Label for='date'>Date of Payment</Label>
<div className='datepicker-cust'>
<DatePicker className='datepicker-cust' onChange={this.inputHandler} value={this.state.date} />
</div>
</FormGroup>
<FormGroup>
<Label for='Place of Receipt Issuance'>Place of Invoicing</Label>
<Input type='text' name='place' id='place' onChange={this.inputHandler} />
</FormGroup>
<FormGroup>
<Button color='info' type='submit'>Save</Button>{' '}
<Button color='secondary' tag={Link} to="/cat/total">Drop</Button>
</FormGroup>
</Form>
</Container>
</div>
);
}
}
export default CostLog;
Additively, case-related snippets inside of stylesheet file:
.datepicker-cust {
width: 500px;
}
.react-datepicker-wrapper, .react-datepicker__input-container {
display: block !important;
}
To be noted, I use div around DatePicker to make this field a bit broader. Whenever it's clicked, picker appears as a single column of days above the field, i.e. all days follow each other in vertical order, nothing like a normal calendar view I want to see. Using developer tool in Chrome, Mozilla, etc., I can suggest the problem takes its origin in zero width of Popper: it has a width equal to 0 and length 200.
This project I'm working on is just my first experience with React and its components. I found out what might be inconsistent here (supposing Popper has wrong size). This solution for a topic-related issue doesn't work in my case: still the same vertical column of numbers instead of two-dimensional calendar pop-up. What needs to be changed in properties to display that as expected?
I had the same problem until I imported the .css file.
import "react-datepicker/dist/react-datepicker.css";

Form validation and error messages not working

I'm currently working on several forms for an app and chose to use Material UI and React Hook Forms to build them. The basic functions are working, which means I can only proceed when all required inputs are filled and I'm getting the desired data.
Unfortunately I'm not able to use the form validation or display of error messages that comes with React Hook Form. It is still using the Material UI validation, even though I followed along to the documentation as close as possible.
Here's what I want to be able to do:
define the min and max length of an input
enter RegEx patterns for password inputs
show the neat looking error messages of React Hook Form
Some of the logic is working, some is not. Can you help me figure out why? Thank you in advance!
import React from 'react';
import { useForm, Controller } from 'react-hook-form';
import { Link } from 'react-router-dom';
// COMPONENTS
import Button from '../01-atoms/inputs/Button';
import Textfield from '../01-atoms/inputs/Textfield';
// MATERIAL UI - CORE
import Fade from '#material-ui/core/Fade';
import Grid from '#material-ui/core/Grid';
import InputAdornment from '#material-ui/core/InputAdornment';
import Typography from '#material-ui/core/Typography';
import Paper from '#material-ui/core/Paper';
// MATERIAL UI - ICONS
import LockSharpIcon from '#material-ui/icons/LockSharp';
import PersonAddSharpIcon from '#material-ui/icons/PersonAddSharp';
export default function SignUp({ i18n, submitSignUpData }) {
const { register, handleSubmit, control, errors } = useForm();
return (
<Grid item xs={12} sm={6} md={3}>
<Fade in>
<Paper elevation={3}>
<Typography align='center' gutterBottom variant='h5'>
{i18n.sign_up.page_title}
</Typography>
<form onSubmit={handleSubmit(submitSignUpData)}>
<Grid container spacing={1}>
<Grid item xs={12}>
<Controller
// This is not working:
rules={register({
required: true,
minLength: 8,
})}
// But this is:
required
as={Textfield}
name='newPassword'
control={control}
defaultValue=''
fullWidth
label={i18n.login.password_placeholder}
variant='outlined'
type='password'
InputProps={{
endAdornment: (
<InputAdornment position='end'>
<LockSharpIcon />
</InputAdornment>
),
}}
/>
{errors.newPassword && 'Your input is required!'}
</Grid>
<Grid item xs={12}>
<Button
fullWidth
content={i18n.sign_up.get_started_button}
variant='contained'
color='secondary'
type='submit'
endIcon={<PersonAddSharpIcon />}
/>
</Grid>
</Grid>
</form>
<Link to='/log-in'>
<Typography>{i18n.login.login_button}</Typography>
</Link>
</Paper>
</Fade>
</Grid>
);
}
Instead of using controller why don't you use TextField of Material UI. I have something like this in my code.
<TextField
name="newPassword"
label="Password"
inputRef={register({ required: true, minLength: 8 })}
defaultValue=''
/>
{
errors.newPassword &&
<ErrorText>
{errors.newPassword.type === "required" ?
'Password is required.' :
`Min character limit for Password is 8.`}
</ErrorText>
}

Cannot get Material UI radio buttons to work with Formik

I am trying to use Material UI radio buttons with Formik, and they are not clicking properly. I've reduced the problem to the following example: https://codesandbox.io/s/amazing-currying-s5vn0
If anyone knows what I might be doing wrong, or if there is a bug in either system, then please let me know. When clicking on the buttons in the above example, they do not stay clicked. I have a more complex react functional component that uses other library components, so I cannot include it here. It is behaving a little differently: the buttons stay clicked even after clicking a different button. It may or may not be the same issue. Thanks in advance.
You need to be rendering the radio buttons inside of the FormikRadioGroup component you are rendering as a Formik Field. That way you can actually pass the props being managed by Formik down to the components to be used, as well as allow the RadioGroup component to make sure only one button is clicked at a time. I added an options prop to provide a way to pass an array of radio options and removed all of the elements you were rendering outside of that component:
const FormikRadioGroup = ({
field,
form: { touched, errors },
name,
options,
...props
}) => {
return (
<React.Fragment>
<RadioGroup {...field} {...props} name={name}>
{options.map(option => (
<FormControlLabel value={option} control={<Radio />} label={option} />
))}
</RadioGroup>
{touched[fieldName] && errors[fieldName] && (
<React.Fragment>{errors[fieldName]}</React.Fragment>
)}
</React.Fragment>
);
};
Fork here.
EDIT: Updated the sandbox with an alternate example using a render function as a child within the Field component.
import { FormControlLabel, Radio, LinearProgress } from '#material-ui/core';
import { Formik, Field } from 'formik';
import { RadioGroup } from 'formik-material-ui';
<Formik {...otherProps}>
{({ isSubmitting }) => (
<Field component={RadioGroup} name="activity">
<FormControlLabel
value="painting"
control={<Radio disabled={isSubmitting} />}
label="Painting"
disabled={isSubmitting}
/>
<FormControlLabel
value="drawing"
control={<Radio disabled={isSubmitting} />}
label="Drawing"
disabled={isSubmitting}
/>
<FormControlLabel
value="none"
control={<Radio disabled={isSubmitting} />}
label="None"
disabled
/>
</Field>
)}
</Formik>;
Now this is documented! Using RadioGroup from formik-material-ui.
https://stackworx.github.io/formik-material-ui/docs/api/material-ui/

Resources