I am trying t make the label is selectable and copyable inside Autocomplete component by setting InputLabelProps={{ sx: { userSelect: "text" } }} inside renderInput. Ideally, I hope I can click or double click to select the label text.
export default function ComboBox() {
return (
<Autocomplete
disablePortal
id="combo-box-demo"
options={top100Films}
sx={{ width: 300 }}
renderInput={(params) => (
<TextField
{...params}
InputLabelProps={{ sx: { userSelect: "text" } }}
label="Movie Name Selection"
/>
)}
/>
);
}
But as it shows here: https://codesandbox.io/s/determined-keller-li1jz7?file=/demo.js:136-508, it is not working.
I even changed it globally and still no luck:
const theme = createTheme({
components: {
MuiInputLabel: {
styleOverrides: {
root: {
userSelect: "text"
}
}
}
}
});
Anyone knows why?
Related
Hi here I am building a form with material ui autocomplete component and react-hook-form useController and useForm, as mui select component's option labels are getting clear on form reset but with autocomplete it is not happening, though its value gets cleared on reset as wanted, so is something wrong with this code or autocomplete issue,
Registered with useController (react-hook-form)
import React from "react";
import Autocomplete from "#mui/material/Autocomplete";
import TextField from "#mui/material/TextField";
import { useController, UseControllerProps } from "react-hook-form";
//type Multi = string;
interface MultiOptionInterface {
label: string;
value: string;
}
interface Props extends UseControllerProps {
label: string;
type?: React.HTMLInputTypeAttribute | undefined;
id: string;
placeholder?: string | undefined;
multiSelectOptions: MultiOptionInterface[];
}
export function RegisteredMultiAutocomplete({
name,
control,
label,
type,
id,
placeholder,
multiSelectOptions
}: Props) {
const {
field: { ref, onChange, ...inputProps },
fieldState: { error },
formState: { isSubmitSuccessful }
} = useController({
name,
control,
defaultValue: ""
});
return (
<Autocomplete
fullWidth
id={id}
multiple
clearOnEscape
options={multiSelectOptions}
getOptionLabel={(option: MultiOptionInterface) => option.label}
renderInput={(params) => (
<TextField
{...inputProps}
{...params}
inputRef={ref}
error={!!error}
helperText={error ? error.message : null}
variant="outlined"
margin="normal"
label={label}
type={type}
placeholder={placeholder}
/>
)}
onChange={(_, data) => {
onChange(data);
return data;
}}
/>
);
}
export default RegisteredMultiAutocomplete;
onSubmit() code
import React from "react";
import { useForm } from "react-hook-form";
import * as Yup from "yup";
import { yupResolver } from "#hookform/resolvers/yup";
import { Box, Button } from "#mui/material";
import { RegisteredMultiAutocomplete } from "./RegisteredMultiAutocomplete";
interface FormInputs {
productCategories: string[];
}
const indcat = [
{ label: "Car", value: "Car" },
{ label: "Bike", value: "Bike" },
{ label: "Bus", value: "Bus" },
{ label: "Truck", value: "Truck" },
{ label: "Van", value: "Van" },
{ label: "Jeep", value: "Jeep" },
{ label: "Tractor", value: "Tractor" }
];
export function App() {
const validateSchema = Yup.object().shape({
productCategories: Yup.array().required("Product category is required")
});
const { handleSubmit, control, reset } = useForm({
mode: "onChange",
resolver: yupResolver(validateSchema)
});
const onSubmit = (data: unknown) => {
console.log(data);
reset();
};
return (
<Box component="form" onSubmit={handleSubmit(onSubmit)}>
<RegisteredMultiAutocomplete
id="product-categories"
name="productCategories"
control={control}
label="Select Product Categories"
type="text"
placeholder="Category"
multiSelectOptions={indcat}
/>
<Button type="submit" color="primary" variant="contained">
{" "}
Submit
</Button>
</Box>
);
}
export default App;
here is the app on codesandbox
on submit the value of autocomplete gets cleared but the option label not
expecting the autocomplete option label should get cleared on reset()
I am using Mui and Gatsby.
I have created the theme in a layout.js like so:
const Layout = ({ children, location, pageTitle, crumbs }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<>
<ThemeProvider theme={theme}>
<Header siteTitle={data.site.siteMetadata?.title || `Title`} />
<CssBaseline />
<Main >
<CustomBreadcrumbs
crumbLabel={pageTitle}
location={location}
crumbs={crumbs}
/>
{children}</Main>
<footer
style={{
marginTop: `2rem`,
}}
>
© {new Date().getFullYear()}, Built with
{` `}
Gatsby
</footer>
</ThemeProvider>
</>
)
}
I have a page component, that has some styles, and are trying to pass theme to page template but when I check the props from the page template Component, theme is undefined and I can also not use it in the styles object I have created.
Page template is like this:
class ProductDetail extends React.Component {
render() {
console.log(this.props)
const product = get(this.props.data, 'contentfulProduct')
const { classes } = this.props
const {
breadcrumb: { crumbs },
} = this.props.pageContext
let images = []
if (product.packagePhoto) {
images.push(product?.packagePhoto)
}
if (product.kibblePhoto) {
images.push(product?.kibblePhoto)
}
if (product.productPhoto) {
images.push(product?.productPhoto)
}
if (product.ambPhoto) {
images.push(product?.ambPhoto)
}
return (
<Layout location={this.props.location} pageTitle={`${product.brand.brandName} ${product.name}`} crumbs={crumbs}>
....some code here
</Layout>
)
}
}
export default withStyles(styles, { withTheme: true })(ProductDetail)
I can not use theme in styles object in page template:
const styles = theme => ({
root: {
width: '100%'
},
paragraph: {
marginBottom: '20px'
},
halfWidthParagraph:{
marginBottom: '20px',
width: '50%',
/* [theme.breakpoints.down('sm')]:{
width: '100%'
} */
}
})
How can I load the "theme" into the Page Component and use it in the styles object?
I'm looking for a text field with multiple inputs as:
Here as you can see I can add new text and on press of enter it saves that keyword.
Can someone guide which package to look for.... I found something similar in material ui autocomplete's costomized hook: https://material-ui.com/components/autocomplete/,
but I don't want it to be drop down I want it to be simply be a text field with option as shown in image.
I cannot find with such functionality or I might be looking work as I don't know proper term for it.
Any guidance will be of great help.
I've included material-ui , reactstrap as this is something I have worked with so if there is any other package also let me know
I was also building something like this few days back. This is what I've built till now.
import {
Chip,
FormControl,
Input,
makeStyles,
} from "#material-ui/core";
import React, { useEffect, useState } from "react";
import "./styles.css";
export default function App() {
const classes = useStyles();
const [values, setValues] = useState(["test"]);
const [currValue, setCurrValue] = useState("");
const handleKeyUp = (e) => {
console.log(e.keyCode);
if (e.keyCode == 32) {
setValues((oldState) => [...oldState, e.target.value]);
setCurrValue("");
}
};
useEffect(() => {
console.log(values);
}, [values]);
const handleChange = (e) => {
setCurrValue(e.target.value);
};
const handleDelete = ( item, index) =>{
let arr = [...values]
arr.splice(index,1)
console.log(item)
setValues(arr)
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<FormControl classes={{ root: classes.formControlRoot }}>
<div className={"container"}>
{values.map((item,index) => (
<Chip size="small" onDelete={()=>handleDelete(item,index)} label={item}/>
))}
</div>
<Input
value={currValue}
onChange={handleChange}
onKeyDown={handleKeyUp}
/>
</FormControl>
</div>
);
}
const useStyles = makeStyles((theme) => ({
formControlRoot: {
display: "flex",
alignItems: "center",
gap: "8px",
width: "300px",
flexWrap: "wrap",
flexDirection: "row",
border:'2px solid lightgray',
padding:4,
borderRadius:'4px',
"&> div.container": {
gap: "6px",
display: "flex",
flexDirection: "row",
flexWrap: "wrap"
},
"& > div.container > span": {
backgroundColor: "gray",
padding: "1px 3px",
borderRadius: "4px"
}
}
}));
Here is the working demo:
One possible way to do this using react-hook-form and Autocomplete using the Chip with renderTags function here is an example:
import {
Box,
TextField,
Autocomplete,
Chip,
} from '#mui/material'
...
const {
handleSubmit,
control,
formState: { errors },
} = useForm()
...
<Box mt={2}>
<Controller
control={control}
name="tags"
rules={{
required: "Veuillez choisir une réponse",
}}
render={({ field: { onChange } }) => (
<Autocomplete
defaultValue={
useCasesData?.tags ? JSON.parse(useCasesData?.tags) : []
}
multiple
id="tags-filled"
options={[]}
freeSolo
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
variant="outlined"
label={option}
{...getTagProps({ index })}
/>
))
}
onChange={(event, values) => {
onChange(values);
}}
renderInput={(params) => (
<TextField
{...params}
label="Métadonnées"
placeholder="Ecriver les métadonnées"
helperText={errors.tags?.message}
error={!!errors.tags}
/>
)}
/>
)}
/>
</Box>
Im building a design system which uses Material UI under the hood. I need to customise the design of a disabled checkbox.
In this code why is the disabled style setting the color to gold not being applied?
import CheckboxMUI from '#material-ui/core/Checkbox';
import CheckBoxOutlineBlankIcon from '#material-ui/icons/CheckBoxOutlineBlank';
import FormControlLabel from '#material-ui/core/FormControlLabel';
const Checkbox = ({ label, onChange, checked, disabled }) => {
const theme = useTheme();
const useStyles = makeStyles({
root: {
color: theme.palette.secondary.main,
'&$disabled': {
color: 'gold',
},
},
});
const classes = useStyles();
return (
<div>
<FormControlLabel
disabled={disabled}
classes={{
root: classes.root,
}}
control={
<CheckboxMUI
disabled={disabled}
checked={checked}
onChange={onChange}
name="checkedA"
color="primary"
icon={
<CheckBoxOutlineBlankIcon
htmlColor={!disabled ? theme.palette.secondary.main : undefined}
/>
}
/>
}
label={label}
/>
</div>
);
};
Material UI's <Checkbox> allows you to provide custom elements for the icon, checkedIcon and indeterminateIcon. In your case, something along these lines would solve your problem:
import React from 'react'
import {
Checkbox as MUICheckbox,
CheckboxProps,
SvgIcon,
} from '#material-ui/core'
import { ReactComponent as CheckboxChecked } from 'assets/svg/ui/CheckboxChecked.svg'
import { ReactComponent as CheckboxUnchecked } from 'assets/svg/ui/CheckboxUnchecked.svg'
import { ReactComponent as CheckboxIndeterminate } from 'assets/svg/ui/CheckboxIndeterminate.svg'
import { ReactComponent as CheckboxDisabled } from 'assets/svg/ui/CheckboxDisabled.svg'
export default function Checkbox(props: CheckboxProps) {
return (
<MUICheckbox
checkedIcon={<SvgIcon component={CheckboxChecked} />}
indeterminateIcon={<SvgIcon component={CheckboxIndeterminate} />}
icon={
<SvgIcon
component={props.disabled ? CheckboxDisabled : CheckboxUnchecked}
/>
}
{...props}
/>
)
}
Which you would then use as follows (which is exactly how I solved this problem):
<Checkbox
disabled={someCondition}
/>
This worked for me:
const useStyles = makeStyles({
root: {
color: theme.palette.secondary.main,
},
label: {
'&.Mui-disabled': {
color: theme.colors.disabledForeground,
},
},
});
<FormControlLabel
disabled={disabled}
classes={{
root: classes.root,
label: classes.label,
}}
I am trying to reproduce a component with Tabs and according filters like the OrderList in the react-admin demo (credentials are admin/password). The source can be found here.
What I have done is the following:
import React, { Fragment } from "react";
import {
List,
TextField,
Datagrid
} from "react-admin";
import Divider from "#material-ui/core/Divider";
import Tabs from "#material-ui/core/Tabs";
import Tab from "#material-ui/core/Tab";
class TabbedDatagrid extends React.Component {
tabs = [
{ id: 1, name: "in service" },
{ id: 2, name: "scrapped" },
{ id: 3, name: "locked" }
];
state = { service: [], scrapped: [], locked: [] };
static getDerivedStateFromProps(props, state) {
if (props.ids !== state[props.filterValues.conditionId]) {
return { ...state, [props.filterValues.conditionId]: props.ids };
}
return null;
}
handleChange = (event, value) => {
const { filterValues, setFilters } = this.props;
setFilters({ ...filterValues, conditionId: value });
};
render() {
const { classes, filterValues, ...props } = this.props;
return (
<Fragment>
<Tabs
variant="fullWidth"
centered
value={filterValues.conditionId}
indicatorColor="primary"
onChange={this.handleChange}
>
{this.tabs.map(choice => (
<Tab key={choice.id} label={choice.name} value={choice.id} />
))}
</Tabs>
<Divider />
<div>
{filterValues.conditionId === 1 && (
<Datagrid {...props} ids={this.state.service}>
<TextField source="id" />
</Datagrid>
)}
{filterValues.conditionId === 2 && (
<Datagrid {...props} ids={this.state.scrapped}>
<TextField source="id" />
</Datagrid>
)}
{filterValues.conditionId === 3 && (
<Datagrid {...props} ids={this.state.locked}>
<TextField source="id" />
</Datagrid>
)}
</div>
</Fragment>
);
}
}
const RollList = ({ classes, ...props }) => (
<List
title="Roll Inventory"
{...props}
filterDefaultValues={{ conditionId: 1 }}
sort={{ field: "name", order: "ASC" }}
perPage={25}
>
<TabbedDatagrid />
</List>
);
export default RollList;
When I run this code:
I see this
Data is not shown, although when I look at the props and the number of records in the right bottom corner I can see that data is there.
The console doesn't show any error (besides missing translations).
I am using the following (relevant) dependencies:
"#material-ui/core": "^3.9.2",
"#material-ui/icons": "^3.0.2",
"ra-data-json-server": "^2.8.0",
"react": "^16.8.4",
"react-admin": "^2.8.1",
"react-dom": "^16.8.4",
"react-scripts": "^2.1.8"
Has anyone an idea what I can do about it?
I found a solution:
I saw that the only difference to the react-admin demo OrderList is that the id of the Tabs is a string whereas in my code it is an integer (like in my data provider).
I changed my code and also my data to be a string as an id instead of an integer.
tabs = [
{ id: 'service', name: 'in service' },
{ id: 'scrapped', name: 'scrapped' },
{ id: 'locked', name: 'locked' }
];
and also in the condition part further down
{filterValues.conditionId === 'service' && (
<Datagrid {...props} ids={this.state.service}>
{//...}
</DataGrid>
)}
... not to forget the default value in the RollList wrapper at the end
filterDefaultValues={{ conditionId: 'service' }}
now it is working.
Thanks to all who thought about it.
Cheers.