Mui Autocomplete with inputLabelProps shrink true in custom theme - material-ui

When using TextField we can add a custom theme to make the label shrink by default
MuiTextField: {
defaultProps: { InputLabelProps: { shrink: true } },
},
When using it with Autocomplete component.
<Autocomplete
fullWidth
options={options}
clearOnBlur
disablePortal
popupIcon={false}
id="combo-box-demo"
renderInput={params => {
return (
<TextField {...params} label="Movie" variant="standard" />
);
}}
/>
What I have tried is that we can add it in autocomplete renderInput props
renderInput={({ InputLabelProps, params })=> {
return (
<TextField {...params}
label="Movie" variant="standard"
InputLabelProps={{
shrink: true,
...InputLabelProps,
}}
/>
);
}}
but the problem is we need to pass it everytime we want to render the autocomplete and it could be easily forgotten.
It would be convenient if we can also make it default in custom theme.
MuiAutoComplete: {
defaultProps: { InputLabelProps: { shrink: true } },
},
is this possible?

I think you should pass shrink: true in the default props to InputLabel itself like that
MuiInputLabel: {
defaultProps: { shrink: true },
},

Related

Quickfilter component width with 100% - Material UI

I'm learning to use Material UI for React js.
I'm implementing the DataGrid control with the Quick filter option.
However, how do I make its width occupy the entire screen?
I didn't find in the documentation if this was possible.
See attached image for better understanding.
Thanks!
<DataGrid
components={{ Toolbar: GridToolbar }}
componentsProps={{
toolbar: {
showQuickFilter: true,
quickFilterProps: { debounceMs: 500 },
},
}}
/>
SampleImage
issue resolved
function QuickSearchToolbar() {
return (
<Box
sx={{
pl: 1,
pr: 1,
pb: 2,
pt: 1,
display: 'flex',
}}
>
<GridToolbarQuickFilter
style={{ flex: 1 }}
quickFilterParser={(searchInput: string) =>
searchInput
.split(',')
.map((value) => value.trim())
.filter((value) => value !== '')
}
debounceMs={600}
/>
</Box>
)
}
<DataGrid
{...rest}
localeText={ptBR.components.MuiDataGrid.defaultProps.localeText}
pageSize={50}
rowsPerPageOptions={[50]}
getRowId={(row) => row.ID}
components={{
Toolbar: QuickSearchToolbar,
LoadingOverlay: LinearProgress
}}
componentsProps={{
toolbar: {
showquickfilter: true,
quickFilterProps: { debounceMs: 600 },
},
}}
/>

material text field label not copyable?

I am using MUI's Text Field component and found there's literally no way to copy the label contents. Is there a way to copy the label somehow?
See the demo here: https://codesandbox.io/s/4ou0l7?file=/demo.tsx
Thanks
It is because material UI is disabling the label selection using CSS.
You can enable it back in a few ways. You can enable it for a certain field or across all of them using the material UI theme override ability.
In order to enable label selection only to one field, you have pass an additional prop to your TextField: InputLabelProps={{ sx: { userSelect: "text" } }}
And here I have provided you with the second way to do that for all the text fields:
import * as React from "react";
import Box from "#mui/material/Box";
import TextField from "#mui/material/TextField";
import { createTheme, ThemeProvider } from "#mui/material/styles";
const theme = createTheme({
components: {
MuiInputLabel: {
styleOverrides: {
root: {
userSelect: "text"
}
}
}
}
});
const StateTextFields = () => {
const [name, setName] = React.useState("Cat in the Hat");
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
return (
<Box
component="form"
sx={{
"& > :not(style)": { m: 1, width: "25ch" }
}}
noValidate
autoComplete="off"
>
<TextField
id="outlined-name"
label="Name"
value={name}
onChange={handleChange}
/>
<TextField
id="outlined-uncontrolled"
label="Uncontrolled"
defaultValue="foo"
/>
</Box>
);
};
export default () => (
<ThemeProvider theme={theme}>
<StateTextFields />
</ThemeProvider>
);
Of course, you can extract this ThemeProvider into a separate file and wrap with it the whole project, not only this file. It is combined just for the example.
I found a way that this can be done using the helperText and my solution is more of a hack. I am using the helperText and positioning it where the label was used to be, giving it a background and bringing it to front using z-index.
Also you can either choose to use the label or replace it with the placeholder depending if you are happy with the animation.
Here is a codesandbox based on your code in case you need it.
<TextField
id="outlined-name"
label="Name"
// placeholder="Name"
value={name}
onChange={handleChange}
helperText="Name"
sx={{
"& .MuiFormHelperText-root": {
top: "-11px",
position: "absolute",
zIndex: "1",
background: "white",
padding: "0 4px",
}
}}
/>

How can I override CSSfor material UI TextField component?

I am using Material UI's Autocomplete/TextField and I want to override its default CSS on hover and when the text field is in focus state.
Default CSS:
Image for default CSS in focused state
I want to change this blue colour when input box is in focus state.
I have tried using ThemeProvider/createTheme hook but it is not helping. Below is the code for createTheme:
import { ThemeProvider, createTheme } from "#mui/material/styles";
const overrideTheme = createTheme({
overrides: {
MuiInput: {
root: {
"&$focused": {
borderColor: "red",
},
},
},
},
});
export default function AutocompleteComponent() {
return (
<ThemeProvider theme={overrideTheme}>
<Autocomplete
classes={classes}
freeSolo
id="free-solo-2-demo"
options={
autocompleteResult ? top100Films.map((option) => option.title) : []
}
renderInput={(params) => (
<TextField
variant="outlined"
{...params}
placeholder="Search..."
InputProps={{
...params.InputProps,
type: "search",
classes: {
root: classes.root,
notchedOutline: classes.notchedOutline,
},
className: classes.input,
endAdornment: false,
}}
/>
)}
/>
</ThemeProvider>
);
}
You have to use the browser dev tools to identify the slot for the component you want to override. Once that's done, you write a CSS file with the class you want to change.
To force the class you can use :
!important
file : styles.css
exemple:
.css-1q6at85-MuiInputBase-root-MuiOutlinedInput-root{
border-radius: 50px!important;
}

React-hook-form + dynamic form: Render element upon dropdown selection

I am working in form using react-hook-form. This form use useFieldArray, it has to be dynamic.
Right now is very simple, it contains a react-select component with a few options and a textfield that get rendered depending on the option that the user select on the select component.
The problem I have is that the textfield component renders when the state updates, which is correct until I add a new group of element to the form. Since the textfield is listening to the same state it doesn't matter which select I use to render the textfield element, it gets rendered in all groups.
I am looking a way to specify which textfield should be rendered when the user change the select.
I the sandbox you can see what I have done. To reproduce the problem click on the "Add"-button and you will see two areas, each one with a select component.
When you choose "Other" in the select component a textfield appears, but not only in the area where the select was changed but in all areas.
How can I avoid that behavior?
https://codesandbox.io/s/vibrant-fast-381q0?file=/src/App.tsx
Extract:
const [isDisabled, setIsDisabled] = useState<boolean>(true);
const { control, handleSubmit, getValues } = useForm<IFormFields>({
defaultValues: {
managerialPositions: [
{
authority: 0,
chiefCategory: 0,
title: 0,
otherTitle: ""
}
]
}
});
useFieldArray implementation:
const {
fields: managerialPositionsFields,
append: managerialPositionsAppend,
remove: managerialPositionsRemove
} = useFieldArray({
name: "managerialPositions",
control
});
Here i update the state when the user select "Other title" in the select component:
const watchChange = (value?: number, i?: number) => {
let values: any = getValues();
if (values.managerialPositions[i].title === 3) {
setIsDisabled(false);
}
};
And here is where I render the button to create a new group of elements and the select component and the textfield that should be rendered if "isDisabled" is false.
{managerialPositionsFields.map((field, index) => {
return (
<Stack className="sectionContainer" key={field.id}>
<Stack horizontal horizontalAlign="space-between">
<StackItem>
<CommandBarButton
iconProps={{ iconName: "AddTo" }}
text="Add"
type="button"
onClick={() => {
managerialPositionsAppend({
authority: 0,
chiefCategory: 0,
title: 0,
otherTitle: ""
});
}}
/>
</StackItem>
</Stack>
<Stack horizontal tokens={{ childrenGap: 20 }}>
<StackItem>
<Label className="select-label requiredIkon">Title</Label>
<Controller
control={control}
name={`managerialPositions.${index}.title`}
render={({ field: { onChange, value, ref } }) => (
<>
<Select
className="react-select-container authoritySelect"
classNamePrefix="react-select"
placeholder="Select title"
options={titelList}
id={`managerialPositions.${index}.title`}
value={
titelList.find((g) => g.value === value)
? titelList.find((g) => g.value === value)
: null
}
onChange={(val) => {
onChange(val.value);
watchChange(val.value, index);
}}
/>
{
// this input is for select validation
<input
tabIndex={-1}
autoComplete="off"
style={{ opacity: 0, height: 0 }}
value={
titelList.find((g) => g.value === value)
? titelList
.find((g) => g.value === value)
.toString()
: ""
}
required={true}
//Without this console will get an error:
onChange={() => {}}
/>
}
</>
)}
/>
</StackItem>
{!isDisabled && (
<StackItem className="">
<Controller
name={`managerialPositions.${index}.otherTitle`}
control={control}
render={({
field: { onChange, name: fieldName, value }
}) => (
<TextField
label="Other title"
name={fieldName}
onChange={(e) => {
onChange(e);
}}
value={value}
/>
)}
/>
</StackItem>
)}
</Stack>
</Stack>
);
})}

ag-Grid Switch goes from checked to unchecked upon down sroll

Getting this weird error where any checked material UI switch becomes unchecked as I scroll down out of that data view.
Below is the Switch return with conditional rendering.
let freeTier = props.params.data.tier;
return freeTier === "FREE" ? (
<FormGroup>
<FormControlLabel
control={
<Switch
disableRipple
focusVisibleClassName={classes.focusVisible}
classes={{
root: classes.root,
switchBase: classes.switchBase,
thumb: classes.thumb,
track: classes.track,
checked: classes.checked
}}
{...props}
/>
}
/>
</FormGroup>
) : null;
And this is where I call the above into cellRendererFramework
cellRendererFramework: params => {
const handleClick = params => {
console.log(params.data);
};
return (
<PaypalSwitch
params={params}
data={params.data}
otherProps={this.props}
onClick={() => handleClick(params)}
/>
);
}
From what it seems like the grid re-renders? I'm getting this error.
ag-Grid: React Component 'cellRendererFramework' not created within
1000ms