Specify ::after style with MaterialUI Grid - javascript

I read Flex-box: Align last row to grid and trying to see if this will work for me too:
.grid::after {
content: "";
flex: auto;
}
but not sure how to specify this in JS styles that I use in MaterialUI:
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
paper: {
height: 140,
width: 140,
},
control: {
padding: theme.spacing(2),
},
fullName: {
marginRight: '3px'
}
}));
Like how do I add after to a MaterialUI Grid?
<Grid className={classes.root} container justify="space-around" spacing={2}>
<CompanyList companies={companies} data-test-id="companyList" />
</Grid>

You could use like below:
const useStyles = makeStyles((theme) => ({
grid: {
// --- some styles
'&::after': {
// --- some style
}
},
}));

It's similar task as to add pseudo element to material-ui component
content attribute needed to be double quoted
Working exammple
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
"&::after": {
content: '""',
width: 40,
height: 40,
backgroundColor: "cyan",
color: "white"
}
},
}));
export default function Material() {
const classes = useStyles();
return (
<div>
<h1>Material</h1>
<Grid
className={classes.root}
container
justify="space-around"
spacing={2}
>
<CompanyList companies={companies} data-test-id="companyList" />
</Grid>
</div>
);
}

Related

How can I insert a basic Search bar in Material UI Data Grid?

For example: refer this sample data grid.
Want to add a basic search bar like:here
How can I add in Data Grid MUI.
Please guide.
Just create a search bar using a label and text input. Aftermath you can update your grid according to the string in your search box by the search filtered data.
In datagrid there is prop components and Toolbar in that prop to pass whatever component you want.
components={{ Toolbar: QuickSearchToolbar }}
and pass props from
componentsProps={{
toolbar: {
value: searchText,
onChange: (event: React.ChangeEvent<HTMLInputElement>) => handleSearch
},
}}
This is a good example to check out:
import * as React from 'react';
import IconButton from '#mui/material/IconButton';
import TextField from '#mui/material/TextField';
import {
DataGrid,
GridToolbarDensitySelector,
GridToolbarFilterButton,
} from '#mui/x-data-grid';
import { useDemoData } from '#mui/x-data-grid-generator';
import ClearIcon from '#mui/icons-material/Clear';
import SearchIcon from '#mui/icons-material/Search';
import { createTheme } from '#mui/material/styles';
import { createStyles, makeStyles } from '#mui/styles';
function escapeRegExp(value: string): string {
return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
const defaultTheme = createTheme();
const useStyles = makeStyles(
(theme) =>
createStyles({
root: {
padding: theme.spacing(0.5, 0.5, 0),
justifyContent: 'space-between',
display: 'flex',
alignItems: 'flex-start',
flexWrap: 'wrap',
},
textField: {
[theme.breakpoints.down('xs')]: {
width: '100%',
},
margin: theme.spacing(1, 0.5, 1.5),
'& .MuiSvgIcon-root': {
marginRight: theme.spacing(0.5),
},
'& .MuiInput-underline:before': {
borderBottom: `1px solid ${theme.palette.divider}`,
},
},
}),
{ defaultTheme },
);
interface QuickSearchToolbarProps {
clearSearch: () => void;
onChange: () => void;
value: string;
}
function QuickSearchToolbar(props: QuickSearchToolbarProps) {
const classes = useStyles();
return (
<div className={classes.root}>
<div>
<GridToolbarFilterButton />
<GridToolbarDensitySelector />
</div>
<TextField
variant="standard"
value={props.value}
onChange={props.onChange}
placeholder="Search…"
className={classes.textField}
InputProps={{
startAdornment: <SearchIcon fontSize="small" />,
endAdornment: (
<IconButton
title="Clear"
aria-label="Clear"
size="small"
style={{ visibility: props.value ? 'visible' : 'hidden' }}
onClick={props.clearSearch}
>
<ClearIcon fontSize="small" />
</IconButton>
),
}}
/>
</div>
);
}
export default function QuickFilteringGrid() {
const { data } = useDemoData({
dataSet: 'Commodity',
rowLength: 100,
maxColumns: 6,
});
const [searchText, setSearchText] = React.useState('');
const [rows, setRows] = React.useState<any[]>(data.rows);
const requestSearch = (searchValue: string) => {
setSearchText(searchValue);
const searchRegex = new RegExp(escapeRegExp(searchValue), 'i');
const filteredRows = data.rows.filter((row: any) => {
return Object.keys(row).some((field: any) => {
return searchRegex.test(row[field].toString());
});
});
setRows(filteredRows);
};
React.useEffect(() => {
setRows(data.rows);
}, [data.rows]);
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
components={{ Toolbar: QuickSearchToolbar }}
rows={rows}
columns={data.columns}
componentsProps={{
toolbar: {
value: searchText,
onChange: (event: React.ChangeEvent<HTMLInputElement>) =>
requestSearch(event.target.value),
clearSearch: () => requestSearch(''),
},
}}
/>
</div>
);
}

Why is this MUI react data grid component rendered 4 times?

I have made a wrapper for MUI Data Grid Component as below:
Selection.tsx:
import * as React from 'react';
import { DataGrid, faIR, GridSelectionModel } from '#mui/x-data-grid';
import type {} from '#mui/x-data-grid/themeAugmentation';
import { createTheme, makeStyles, ThemeProvider } from '#mui/material/styles';
import { useRef, useState } from "react";
import { TablePagination } from "#mui/material";
import Stack from "#mui/material/Stack";
import DeleteIcon from '#mui/icons-material/Delete';
export default function ControlledSelectionServerPaginationGrid(props: any) {
const theme = createTheme(
{
breakpoints: {
values: {
xs: 300,
sm: 600,
md: 900,
lg: 1200,
xl: 1536
}
},
palette: {
primary: { main: '#1976d2' },
},
components: {
MuiDataGrid: {
styleOverrides: {
root: {
display: "flex",
flexDirection: "column-reverse",
borderRadius: '0',
paddingRight: '0px',
},
menu: {
direction: "rtl",
},
footerContainer: {
borderBottom: '1px solid #e0e0e0'
},
cell: {
textAlign: 'right',
'&:last-child': {
textAlign: 'center',
},
}
}
},
MuiTablePagination: {
styleOverrides: {
root: {
borderRadius: 'none',
direction: 'rtl',
},
displayedRows: {
margin: 0,
direction: 'ltr',
},
actions: {
direction: "ltr"
}
}
},
MuiToolbar: {
styleOverrides: {
root: {
display: 'flex',
flexDirection: 'row-reverse',
}
}
},
MuiTableCell: {
styleOverrides: {
root: {
border: 'none'
}
}
}
},
},
faIR,
);
const [page, setPage] = useState<number>(0);
const { packages, loading } = props.FetchData(page);
const [selected, setSelected] = useState<any>([]);
const [rowsPerPage, setRowsPerPage] = useState<number>(15);
const handleChangePage = (event: React.MouseEvent<HTMLButtonElement> | null, pageNumber: number) => {
setPage(pageNumber);
};
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
setRowsPerPage(parseInt(event.target.value));
setPage(0);
};
const CustomFooter = () => {
return (
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
sx={{
borderBottom: '1px solid #e0e0e0'
}}
>
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
sx={{
marginRight: '20px',
}}
>
{
selected && selected.length > 0 && (
<DeleteIcon sx={{color: "gray", cursor: 'pointer'}} onClick={() => alert('deleted them all')} />
)
}
</Stack>
<CustomPagination/>
</Stack>
)
}
const CustomPagination = () => {
return (
<TablePagination
count={packages?.meta?.last_page}
page={page}
onPageChange={handleChangePage}
rowsPerPage={rowsPerPage}
labelRowsPerPage={false}
onRowsPerPageChange={handleChangeRowsPerPage}
rowsPerPageOptions={[15, 30, 45, 60]}
/>
)
}
return (
<div style={{ height: '790px', width: '100%' }}>
<ThemeProvider theme={theme}>
{
loading ? (
<div>
loading
</div>
) : (
<DataGrid
rows={packages.data}
getRowId={(row) => row.uuid}
columns={props.columns}
pagination
components={{Footer: CustomFooter}}
checkboxSelection
disableSelectionOnClick
hideFooterSelectedRowCount
loading={loading}
onSelectionModelChange={(ids) => {
setSelected(ids);
}}
/>
)
}
</ThemeProvider>
</div>
);
}
I have the below hook as well which I'm passing to the above component as FetchData:
usePackages.tsx:
export default function usePackages(page: number) {
const [loading, setLoading] = useState<boolean>(false);
const [packages, setPackages] = useState<any>({
data: [],
meta: {},
links: {}
});
useEffect(() => {
setLoading(true);
getListOfAllPackages(page)
.then(data => {
setPackages({
...data.data,
});
setLoading(false);
})
.catch(error => {
setLoading(false);
});
}, [page]);
return { packages, loading };
Now the way I'm using the above components is just like below:
Packages.tsx:
import usePackages from "../../../hooks/Package/usePackages";
const configValues = (params: any) => {
return `${params.row.config.hdd}, ${params.row.config.cpu}, ${params.row.config.ram}`
}
const columns = [
{
field: "product_name",
headerName: "Product Name",
width: '200',
flex: 1
},
{
field: "name",
headerName: "Name",
width: '400',
flex: 1
},
{
field: "config",
headerName: "Config",
width: '150',
flex: 1,
valueGetter: configValues,
},
{
field: "description",
headerName: "Description",
width: '350',
flex: 1
},
{
field: 'actions',
type: 'Actions',
width: '100',
flex: 1,
},
]
return (
<div style={{ display: 'flex', height: '100%', marginTop: '64px'}}>
<div style={{ flexGrow: 1 }}>
<ControlledSelectionServerPaginationGrid columns={columns} FetchData={usePackages}/>
</div>
</div>
)
Now my Selection.tsx renders nearly 4 times and making the other components open with delay like modals and the Side Nav, I tried to console log everything and found out it's because of my passed hook props.FetchData that Selection.tsx re-renders itself, hence checking usePackages.tsx and finding out nothing is wrong. I've used such pattern previously and didn't confront such related issues.
I'm not sure the exact reason for these rerenders though. But I saw some potential things that may affect it.
First, I think it's better to put some variables like theme outside of your component body. Because on each rerender, this variable recreates.
Then, make sure to memorize some of the functions that you are using inside your component body like CustomPagination and CustomFooter with the useMemo hook. Because these are recreating with every rerender that happens, too.
After that, based on my experience, it's better to not pass functions through props. Because React can not compare functions for previous props and next props for each rerender. It's better to abstract functions and import them into the component file that you need.
Here, you can import usePackages directly from Selection.tsx instead of using it from props.
That's the idea behind hooks.

Enlarge placeholder lineHeight and fontSize of InputBase in material UI

I am a newbie of material UI and I am using it for my website
I want the placeholder of the inputbase in material ui to increase their lineHeight and fontSize but I don't know to access to the placeholder API to customize it, please help me out
this is my current screen
this is what I expected
this is my code
import React, { useContext } from 'react';
import { InputBase, Grid, makeStyles } from '#material-ui/core';
import { SearchBoxContext } from '../../providers/SearchBoxContextProvider';
const useStyles = makeStyles((theme) => ({
largeSearchBoxContainer: (props) => {
return {
[theme.breakpoints.up('sm')]: {
textAlign: 'left',
display: 'none',
},
};
},
hideSearchBox: {
display: 'none',
},
InputBaseStyle: {
'& $placeholder': {
fontSize: '88px',
lineHeight: '88px',
},
},
}));
export default function LargeSearchBox() {
const classes = useStyles();
var { openSearchBox } = useContext(SearchBoxContext);
return (
<>
<Grid
className={classes.largeSearchBoxContainer}
container
xs={12}
sm={12}
direction="row"
justify="flex-start"
alignItems="center"
>
<Grid item xs={12} sm={12} className={openSearchBox ? null : classes.hideSearchBox}>
<InputBase
placeholder="Search…"
className={classes.InputBaseStyle}
fullWidth
autoFocus
margin
inputProps={{ 'aria-label': 'search' }}
/>
</Grid>
</Grid>
</>
);
}
You need to override the .MuiInputBase-input CSS via the input Rule name.
In my example below, I took advantage of the classes object property as explained in the documentation.
const useStyles = makeStyles((theme) => ({
InputBaseStyle: {
"&::placeholder": {
fontSize: "88px",
lineHeight: "88px"
},
height: "120px"
}
}));
<InputBase
placeholder="Search…"
// className={classes.InputBaseStyle} you can omit this
fullWidth
autoFocus
margin
inputProps={{ "aria-label": "search" }}
classes={{
input: classes.InputBaseStyle
}}
/>
CodeSandBox: https://codesandbox.io/s/restless-dawn-b5xvv?file=/src/App.js
InputBase CSS Rule names: https://material-ui.com/api/input-base/#css

How to change material-ui slider thumb style when it's disabled

I am able to modify the Slider style using withStyles:
const CustomSlider = withStyles(theme => ({
disabled: {
color: theme.palette.primary.main
},
thumb: {
height: 24,
width: 24,
},
}))(Slider);
but the height and width of the thumb is only applied when the component is disabled={false}.
is there a simple way to change the slider height and width on disabled={true}?
Demo:
https://codesandbox.io/s/slide-thumb-size-gxb4g?file=/demo.js
Reason
The style is been overridden by className Mui-disabled
You can see the color will keep.
How to solve it
Override the style of MuiSlider-thumb or Mui-disabled
One option: use MUI className nesting selector
"& .MuiSlider-thumb": {
height: 24,
width: 24
}
Notice withStyles attributes refer to the CSS API, you can use className + style hooks instead to customize the className which is not exposed by the CSS API like that
Full code:
import React from "react";
import Slider from "#material-ui/core/Slider";
import Paper from "#material-ui/core/Paper";
import { withStyles, makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
margin: {
margin: theme.spacing(10),
"& .MuiSlider-thumb": {
height: 24,
width: 24
}
}
}));
const CustomSlider = withStyles(theme => ({
disabled: {
color: theme.palette.primary.main
},
thumb: {
// color: "red"
}
}))(Slider);
export default function MyCustomSlider() {
const classes = useStyles();
return (
<div>
<Paper className={classes.margin}>
<CustomSlider
defaultValue={[10, 15]}
min={0}
max={20}
valueLabelDisplay="on"
disabled={true}
/>{" "}
<CustomSlider
defaultValue={[5, 7]}
min={0}
max={20}
valueLabelDisplay="on"
disabled={false}
/>{" "}
</Paper>
</div>
);
}
Update
For withStyles
const styles = theme =>
createStyles({
margin: {
margin: theme.spacing(10)
},
thumb: {
"& .MuiSlider-thumb": {
height: 24,
width: 24
}
}
});
function MyCustomSlider(props) {
// const classes = useStyles();
return (
<div>
<Paper className={props.classes.margin}>
<Slider
defaultValue={[10, 15]}
min={0}
max={20}
valueLabelDisplay="on"
disabled={true}
className={props.classes.thumb}
/>{" "}
<Slider
defaultValue={[5, 7]}
min={0}
max={20}
valueLabelDisplay="on"
disabled={false}
/>{" "}
</Paper>
</div>
);
}
export default withStyles(styles)(MyCustomSlider);
disabled: {
"& .MuiSlider-thumb ": {
display: "none",
},
"& .MuiSlider-track": {
backgroundColor: "#e0e0e0",
},
},
This is withStyle solution , where user can change the styling of slider and its sub component.

color change for the loading bar component of material ui

I am trying to learn material ui.
I am trying to change the css of the loading bar.
I referred to the documentation and used colorPrimary classes
but its not changing.
can you tell me how to fix it so taht in future I will fix it myself
providing my code snippet below.
all my code is in ReceipeReviewCardList.js
https://codesandbox.io/s/2zonj08v5r
const styles = {
root: {
flexGrow: 1
},
colorPrimary: {
color: "green"
}
};
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<LinearProgress
className={classes.colorPrimary}
variant="determinate"
value={this.state.completed}
you can use example as was in the reply of the issue in material ui github project: https://github.com/mui-org/material-ui/issues/12858#issuecomment-421150158
import React, { Component } from 'react';
import { withStyles } from '#material-ui/core/styles';
import { LinearProgress } from '#material-ui/core';
class ColoredLinearProgress extends Component {
render() {
const { classes } = this.props;
return <LinearProgress {...this.props} classes={{colorPrimary: classes.colorPrimary, barColorPrimary: classes.barColorPrimary}}/>;
}
}
const styles = props => ({
colorPrimary: {
backgroundColor: '#00695C',
},
barColorPrimary: {
backgroundColor: '#B2DFDB',
}
});
export default withStyles(styles)(ColoredLinearProgress);
It works perfect.
You can override the background colors with makeStyles.
On makeStyles file:
export const useStyles = makeStyles(() => ({
root: {
"& .MuiLinearProgress-colorPrimary": {
backgroundColor: "red",
},
"& .MuiLinearProgress-barColorPrimary": {
backgroundColor: "green",
},
},
})
Import and use:
import { useStyles } from "./myFile.style";
...
const classes = useStyles();
...
<div className={classes.root}>
<LinearProgress />
</div>
It is because you set the CSS is not correctly,
const styles = {
root: {
flexGrow: 1
},
colorPrimary: {
background: 'green'
}
};
not:
const styles = {
root: {
flexGrow: 1
},
colorPrimary: {
color: "green",
}
};
Hope it help!
If you want to overwrite with sx:
sx={{
'& .MuiLinearProgress-bar1Determinate': {
backgroundColor: 'red',
}
}}
the color of the main bar is set as the BACKGROUNDCOLOR, NOT the COLOR
For Material UI v5 (#mui)
<LinearProgress sx={{
backgroundColor: 'white',
'& .MuiLinearProgress-bar': {
backgroundColor: 'green'
}
}}
variant="determinate"
value={10}/>
I did do it by this way, creating your own theme
import {createMuiTheme, MuiThemeProvider } from '#material-ui/core/styles';
const theme = createMuiTheme({
palette: {
secondary: {
main: '#42baf5'
}
}
})
<MuiThemeProvider theme={theme}>
<LinearProgress color="secondary"/>
</MuiThemeProvider>
An easy workaround i stumbled upon which doesn't seem too much of a hack:
<LinearProgress
className="VolumeBar"
variant="determinate"
value={volume}
/>
.VolumeBar > * { background-color:green; }
.VolumeBar{background-color:gray ;}
The first rule makes the progress appear green(completed part).
The second rule takes care of the uncompleted part .
const BorderLinearProgress = withStyles((theme: Theme) =>
createStyles({
root: {
width: '95%',
height: 10,
borderRadius: 5,
marginTop: 8,
marginBottom: 20
},
colorPrimary: {
backgroundColor: Liquidity.colors.main.pink,
},
bar: {
borderRadius: 5,
backgroundColor: Liquidity.colors.main.yellow,
},
}),
)(LinearProgress);
This worked for me (Material ui version 4):
progressbar: {
background: 'yellow',
'& .MuiLinearProgress-bar': {
backgroundColor: theme.palette.success.main,
},
},
And then
<LinearProgress
className={classes.progressbar}
variant="determinate"
value={30}
/>
That have worked for me !
First set a className to the LinearProgress component
<LinearProgress
className="custom-class"
variant="determinate"
value={MyValue}
/>
then style it from your attached css file as shown in the following :
.custom-class > * { background-color:green !important; }
.custom-class{background-color:gray !important;}
using the !important tag is premordial to override the original color.
style: progress: { color: 'red' },
Component:
<LinearProgress color="inherit" className={classes.progress} />

Categories

Resources