How to remove an option from MUI Datagrid Column Show/Hide panel - javascript

I'm trying to control which columns will show up on the <GridToolbarColumnsButton/> component inside of the MUI Datagrid toolbar (see below image)
Preferred solution:
Use the API thought I haven't found any existing functionality to do this or even any docs for the <GridToolbarColumnsButton/> for that matter
My workaround so far:
Use vanilla js to target the row inside of the panel containing the text 'Commodity', add a class to it, and then pass display:'hide' for that class in the DataGrid componentsProps.
Problem with it is that since the columns panel isn't mounted at the initial render, it doesn't hide the Commodity option until after I open the panel and then force a re-render.
useEffect( () => {
var divs = document.querySelectorAll('div .MuiDataGrid-columnsPanelRow')
for (let i = 0; i < divs.length; i++) {
if (divs[i].textContent === 'Commodity') {
divs[i].classList.add("column-panel-cust");
}
}
})
<DataGridPro
...
componentsProps={{
panel: {
sx: {
paddingTop: '15px',
'& .column-panel-cust': {
display: 'none',
},
},
},
/>

Could not find an API hook for this but was able to get it working by adding an onBlur to <GridToolbarColumnsButton onBlur={handleOnBlur}/> that would run the function:
const handleOnBlur = () => {
var divs = document.querySelectorAll('div .MuiDataGrid-columnsPanelRow')
for (let i = 0; i < divs.length; i++) {
if (divs[i].textContent === 'Commodity') {
divs[i].classList.add("column-panel-cust");
}
}
}
which added the column-panel-cust class to the div with the text commodity, this class's styling was passed in the DataGrid componentsProps:
<DataGridPro
...
componentsProps={{
panel: {
sx: {
paddingTop: '15px',
'& .column-panel-cust': {
display: 'none',
},
},
},
/>

You could also go with just some pure css. You just need to target the position of the column. For instance, I am doing the same thing here hiding the Menu from the GridToolbarColumnsButton (last item).
<DataGrid
columns={columnsDataGrid}
loading={loadingDataSubcriptions}
rows={supplierList}
components={{
Toolbar: customToolbarSupplier,
}}
componentsProps={{
panel: {
sx: {
'& .MuiDataGrid-columnsPanelRow:last-child': {
display: 'none',
},
},
},
}}
/>

Related

How can I select all the classNames that ends with a given word in MUI sx property?

I am using MUI and I need to change some properties that have classNames with these random IDs as prefixes. How can I select, for example, the first one like:
'& endsWith(MuiAccordionDetails-root)'
I want to do like this because these random IDs are changing constantly
const Styles = {
accordion:{
p:0,
'& .css-15v22id-MuiAccordionDetails-root':{
p:0,
},
'& .css-10gwilr-MuiButtonBase-root-MuiAccordionSummary-root':{
px: '10px',
},
'& .MuiCollapse-root':{
mx:'20px'
}
},
}
In Mui elements, classNames Are like this MuiCollapse-root MuiCollapse-vertical MuiCollapse-entered css-c4sutr so there is always a separate class for each element, and class name by ids are changed in each render, and always separate from main class names like above,
so you can select your element by:
const Styles = {
accordion: {
p: 0,
"& .MuiAccordionDetails-root": {
p: 0
},
"& .MuiButtonBase-root- .MuiAccordionSummary-root": {
px: "10px"
},
"& .MuiCollapse-root": {
mx: "20px"
}
}
};

Target Specific Select in DataGrid Pagination

I want to change the font size of all numbers (10, 25, and 50 as seen in this screenshot below) inside rows per page select element inside a pagination of a DataGrid component.
I inspected each number and I got .MuiMenuItem-root as the selector for each element.
Then I changed the font-size and color (just to prove that .MuiMenuItem-root was the right selector) as seen in the screenshot below.
The result was successful.
When I applied the selector in my code, the font-size didn't work (nothing changed).
Here is my code:
CustomDataGrid.js:
import { DataGridPro } from '#mui/x-data-grid-pro'
import { withStyles } from '#material-ui/core/styles'
const CustomDataGrid = withStyles((theme) => ({
root: {
// ROOT
height: '100%',
border: 'none',
...some code here
// PAGINATION
'& .MuiTablePagination-caption': {
fontSize: 12,
},
'& .MuiTablePagination-select': {
fontSize: 12,
},
'& .MuiMenuItem-root': {
fontSize: 12,
},
'& .MuiIconButton-root': {
padding: 8,
},
},
}))(DataGridPro)
export default CustomDataGrid
dependencies (in package.json file):
"#material-ui/core": "^4.12.3",
"#material-ui/icons": "^4.11.2",
"#material-ui/lab": "^4.0.0-alpha.60",
"#material-ui/styles": "^4.11.4",
"#mui/x-data-grid": "^4.0.0",
"#mui/x-data-grid-pro": "^4.0.0",
So how can I change the font-size of all numbers inside the select element inside a pagination of a Data Grid component using withStyles?
DataGrid has a Pagination slot to let you override the pagination component and its props. It uses TablePagination behind the scene, which exposes the SelectProps to let you override the Select component. The Select itself has a MenuProps which allows you to override the props of the dropdown overlay. So with all of that, this is what you have to do to target the right component:
<DataGrid
pagination
{...data}
componentsProps={{
pagination: {
SelectProps: {
MenuProps: {
sx: {
color: "red",
"& .MuiMenuItem-root": {
fontSize: 30
}
}
}
}
}
}}
/>

How to custom color text and icon in TableSortText component of Material-ui?

What I'm trying to do:
I am trying to provide the user the option to provide custom styling to my EnhancedTable component by passing in a styles object containing properties such as headCellColor, headCellBackgroundColor, bodyCellColor, bodyCellBackgroundColor etc which can be used to color the cells in TableHead and TableBody.
In the TableHead component, I use a TableSortLabel in a way similar to what they've done in this material-ui docs example: https://material-ui.com/components/tables/#sorting-amp-selecting
I wish to custom color the text and the arrow icons on hover and when active based on the props provided by the user.
Let's see the colors of TableSortLabel in different situations:
The color of the text is grey initially and there is no arrow. When mouse is hovered over it, a grey arrow appears and the text turns black. On clicking it, active state is set, the grey arrow turns black and the text turns black permanently until active state is removed.
What I've tried so far:
const useStyles = makeStyles({
tableSortLabel: props => ({
backgroundColor: "blue",
color: props.headCellColor,
fill: props.headCellColor,
"&:hover": {
backgroundColor: "blue"
}
})
});
function EnhancedTableHeadCell(props) {
const { isActive, onHoverSortState, clickHandler, ...otherProps } = props;
const classes = useStyles(props.styles);
return (
<FancyTableCell styles={props.styles} {...otherProps}>
<TableSortLabel
active={isActive}
classes={{
icon: classes.tableSortLabel,
active: classes.tableSortLabel
}}
direction={onHoverSortState}
onClick={clickHandler}
>
{props.children}
</TableSortLabel>
</FancyTableCell>
);
}
This is what it looks like in the browser:
https://i.postimg.cc/fW7W2MRB/c1.jpg
The first one is a normal header, the second is on hover and the third is when clicked (active state).
From what we can observe, the text color is totally unaffected by the color css property in all the three cases (normal, hover, active). On hover, backgroundColor only affects the icon and not the text. However, we can see that backgroundColor affects the text when it is active. Everything is going as expected with the icon. The only issue is with the text.
What could I be possible doing wrong? How can I solve my problem?
What worked for me is:
const StyledTableSortLabel = withStyles((theme: Theme) =>
createStyles({
root: {
color: 'white',
"&:hover": {
color: 'white',
},
'&$active': {
color: 'white',
},
},
active: {},
icon: {
color: 'inherit !important'
},
})
)(TableSortLabel);
You can reference the following for increasing css specificity:
https://material-ui.com/customization/components/#pseudo-classes
Solution for your problem is following:
MuiTableSortLabel: {
root: {
color: textPrimary,
// if you want to have icons visible permanently
// '& $icon': {
// opacity: 1,
// color: primaryMain
// },
"&:hover": {
color: primaryMain,
'&& $icon': {
opacity: 1,
color: primaryMain
},
},
"&$active": {
color: primaryMain,
// && instead of & is a workaround for https://github.com/cssinjs/jss/issues/1045
'&& $icon': {
opacity: 1,
color: primaryMain
},
},
},
}
This restyling I use globally via my ThemeProvider, but you can of course use it individually in your single component by using "withStyles" HOC (see "BootstrapButton" in example)
I could'nt find a proper way to do it so I came up with a temporary solution overriding the material ui css.
I added this to my global css:
.MuiTableSortLabel-root.MuiTableSortLabel-active,
.MuiTableSortLabel-root:hover,
.MuiTableSortLabel-icon {
color: inherit !important;
}
Worked for me with Mui5:
sx = {
{
'&.MuiTableSortLabel-root': {
color: 'white',
},
'&.MuiTableSortLabel-root:hover': {
color: 'blue',
},
'&.Mui-active': {
color: 'blue',
},
'& .MuiTableSortLabel-icon': {
color: 'blue !important',
},
}
}
'&.MuiTableSortLabel-root' <-- no space &.
'&.Mui-active' <-- no space &.
'& .MuiTableSortLabel-icon' <-- space

How to create button with text under icon by reactjs?

Now, I have component like this:
code of it:
import React from "react";
import {withStyles} from "material-ui/styles";
import Settings from "material-ui-icons/Settings";
import Button from "material-ui/Button";
const styles = {
button: {
color: "primary",
height: 95,
width: 95,
disableRipple: "true",
focusRipple: "true",
},
icon: {
height: 35,
width: 35,
display: "block",
float: "none",
},
text: {
height: 35,
width: 35,
display: "block",
float: "none",
marginTop: 10,
},
};
/* eslint-disable react/prop-types */
const IconedLabel = ({classes}) => (
<section>
<Button className={classes.iconButton} variant="raised" color="primary">
<Settings className={classes.icon}/>
<div className={classes.text}>Message</div>
</Button>
</section>
);
export default withStyles(styles)(IconedLabel);
But need to button, that in top part contains icon and text message in bottom.
I use reactjs and material-ui lib from here https://material-ui-next.com/demos/buttons/
The Button component uses flexbox to control the layout/alignment of content. To align the content vertically (so the icon is above the text), you can simply change the flex-direction to column.
This style needs to be applied to an element inside the button component, not to the root element. You can use the classes property to override all of the styles in a component.
In this case, you want to add flexDirection: column to the label class.
Documentation on class overrides in material ui v1
Here's a working example. Hope it helps.
const [React, ReactDOM, Button, Settings, withStyles] = [window.React, window.ReactDOM, window['material-ui'].Button, ({className}) => <i className={`material-icons ${className}`}>settings</i>, window['material-ui'].withStyles]
// Ignore code above this line
const styles = theme => ({
button: {
height: 95, // setting height/width is optional
},
label: {
// Aligns the content of the button vertically.
flexDirection: 'column'
},
icon: {
fontSize: '32px !important',
marginBottom: theme.spacing.unit
}
})
const CustomButton = ({ classes }) => (
<Button
/* Use classes property to inject custom styles */
classes={{ root: classes.button, label: classes.label }}
variant="raised"
color="primary"
disableRipple={true}
>
<Settings className={classes.icon} />
Message
</Button>
)
const WrappedCustomButton = withStyles(styles)(CustomButton)
ReactDOM.render(<WrappedCustomButton />, document.querySelector('#root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script><script src="https://unpkg.com/material-ui#1.0.0-beta.40/umd/material-ui.production.min.js"></script><link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"><div id="root" />
A (potentially bad) solution would simply be:
.MuiIconButton-label {
flex-direction: column
}
I say bad, because you might want to use it in it's standard format elsewhere.
What I opted to do was add a class name nav-bar-icon-wrapper to the IconButton & set the flex direction in it's parent:
.nav-bar-icon-wrapper {
flex-direction: column
}
.MuiIconButton-label {
flex-direction: inherit
}
If I run into instance later where I want the icon/label button to be standard, I'll just add a new class default-icon-wrapper and css that handles that:
.default-icon-wrapper {
flex-direction: row
}
FWIW:
I preach the BEM http://getbem.com/introduction/ convention AND that whenever you make a component, you add an optional modifier prop.
I have functions in a shared dir that looks these:
export function BEMifyThis(modifier) {
return (klass) => BEMify(klass, modifier)
}
export function BEMify(klass, modifier=false) {
if (modifier) {
klass += ` ${klass}-${modifier}`
}
return klass
}
Then I use that everywhere in my component so the user can access the component elements as a group or individually using their modifiers.
import {BEMifyThis} from '../shared/bem'
const BEMify = BEMifyThis(this.props.modifier)
className={"navbar__menu_item")}
becomes
className={BEMify("navbar__menu_item")}
so something like navbar__menu_item becomes navbar__menu_item navbar__menu_item-logout

How to align text in Draft.js

I'm wondering how to align text in Draft.js just like on the picture below.
I have searched this several days, but I haven't found the solution.
After reading the source code, I found a way for it. Using blockRenderMap, you can add some custom block types like this:
const blockRenderMap: Record<string, DraftBlockRenderConfig> = {
'header-one-right': {
element: 'h1',
wrapper: <StyleHOC style={{ ...blockStylesMap['header-one'], display: 'flex', justifyContent: 'flex-end' }} />,
},
'header-two-right': {
element: 'h2',
wrapper: <StyleHOC style={{ ...blockStylesMap['header-two'], display: 'flex', justifyContent: 'flex-end' }} />,
},
'header-three-right': {
element: 'h3',
wrapper: <StyleHOC style={{ ...blockStylesMap['header-three'], display: 'flex', justifyContent: 'flex-end' }} />,
},
'unstyled-right': {
element: 'div',
wrapper: <StyleHOC style={{ ...blockStylesMap['unstyled'], display: 'flex', justifyContent: 'flex-end' }} />,
},
};
I use flex to avoid wasting time to find a away to override the internal style .public-DraftStyleDefault-ltr.
StyleHOC is quite simple:
const StyleHOC: React.FC<Props> = ({ style, children }) => {
const childrenWithStyle = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { style });
}
return child;
});
return <>{childrenWithStyle}</>;
};
And then you can toggle the blockType using RichUtils.toggleBlockType(editorState, blockType).
The Editor component has a div with the class .public-DraftStyleDefault-ltr. This controls the text alignment of each paragraph that you write. As you create more paragraphs, more of these divs are created to contain the text. The text is wrapped in a span element and .public-DraftStyleDefault-ltr has a default alignment of text-align: left.
I created some css classes for text-align: left, text-align: center, text-align: right and text-align: justify and added this basic for loop to my component for creating text alignment buttons.
const textBlock = document.querySelectorAll(".public-DraftStyleDefault-ltr");
for (let i = 0; i < textBlock.length; i++) {
textBlock[i].classList.toggle(this.props.style);
}
this.props.style is the name of the css class that determines the text-alignment I wanted.
It is a pretty basic fix since this way when you click align right say, the whole document is aligned right. I am planning to work on this so only the selected text is aligned so should be able to update this answer soon. Hope it helps in some way
I tried to make almost the same thing. But my trouble was in text-align property, which was correctly set to block span, but .public-DraftStyleDefault-ltr doesn't react to it.
So, I have made next decision, which get the first div child, and copy it's params:
const paragraphs: any = document.querySelectorAll(".public-DraftStyleDefault-ltr");
for (let i = 0; i < paragraphs.length; i++) {
const paragraph = paragraphs.item(i);
if (paragraph) {
const firstItem = paragraph.querySelectorAll('*').item(0);
// Apply to the parent the first child style
paragraph.style.textAlign = firstItem.style.textAlign;
}
}
To change block alignment you can:
1- set alignment data
const modifiedBlockState = Modifier.setBlockData(editorState.getCurrentContent(),
editorState.getSelection(),Map({align:'align-center'}));
setEditorState(EditorState.push(modifiedBlockState,'change-block-data'));
2- use it in styling function
/*
JSX
blockStyleFn={ block => block.getData().get('align')
this will return 'align-center|left|right' which will be assigned as a classname
*/
<Editor blockStyleFn={ block => block.getData().get('align')} .../>
//CSS
.align-center div{
text-align: center;
}
.align-right div{
text-align: right;
}
.....

Categories

Resources