Material ui TextField Label text problem, why is not label text visible? - reactjs

I learn ReactJs and material-ui and now I have a problem with material TextField.
The code below creates this:
The problem I have is that the label="Tag Name" does not show the label text in the TextField.
When I click the TextField it looks like this:
The label label="Tag Name" should be visible in the TextFiled like this:
Please advice what is wrong?
import React from 'react';
import { connect } from 'react-redux';
import Dots from 'react-activity/lib/Dots';
import 'react-activity/lib/Dots/Dots.css';
import { Button, FormControl, InputLabel, Select, TextField, MenuItem } from '#material-ui/core';
import { withStyles } from '#material-ui/core/styles';
import { compose } from 'recompose';
import { changeDisplayName } from '../../../../../redux/userData/user.actions';
const styles = theme => ({
root: {
backgroundColor: theme.palette.primary.light,
// textAlign: 'center',
padding: '10px',
margin: 'auto',
display: 'flex',
justifyContent: 'space-around',
},
tagTextField: {
textAlign: 'left',
padding: '8px',
margin: '5px',
border: 'none',
borderRadius: '2px',
fontSize: '12pt',
// background: 'blue',
},
input: {
background: 'white',
color: 'black',
},
changeNameButton: {
backgroundColor: theme.palette.primary.main,
boxShadow: theme.shadows[5],
border: 'none',
borderRadius: '2px',
color: 'white',
margin: '5px',
padding: '8px',
cursor: 'pointer',
'&:hover': {
cursor: 'pointer',
backgroundColor: theme.palette.primary.dark,
},
'&:active': {
cursor: 'pointer',
backgroundColor: theme.palette.primary.dark,
},
'&:disabled': {
cursor: 'default',
color: 'gray',
backgroundColor: theme.palette.primary.main,
},
},
});
class AddTag extends React.Component {
constructor(props) {
super(props);
this.state = {
tagName: '',
categoryName: 'aaa',
categoryNames: ['aaaa', 'bbbb', 'cccc', 'dddd', 'fff'],
};
}
submit = () => {
// let todoListCopy = [...this.state.todoList];
// todoListCopy.push({
// todoName: this.state.todoName,
// userName: this.state.userName,
// });
// this.setState({
// todoName: '',
// todoList: todoListCopy,
// });
};
changeCategoryName = categoryName => {
this.setState({
categoryName,
});
};
changeTagName = tagName => {
this.setState({
tagName,
});
};
render() {
const { classes } = this.props;
const { tagName, categoryName, categoryNames } = this.state;
return (
<div className={classes.root}>
<TextField
className={classes.tagTextField}
id="outlined-basic"
label="Tag Name"
variant="outlined"
value={tagName}
onChange={e => this.changeTagName(e.target.value)}
autoComplete="off"
InputProps={{
className: classes.input,
}}
/>
<FormControl>
<InputLabel id="demo-simple-select-helper-label">Category</InputLabel>
<Select
labelId="demo-simple-select-helper-label"
id="demo-simple-select-helper"
value={categoryName}
onChange={e => this.changeCategoryName(e.target.value)}
>
{categoryNames &&
categoryNames.map((element, index) => {
return (
<MenuItem value={element} key={index}>
{element}
</MenuItem>
);
})}
</Select>
</FormControl>
<Button
className={classes.changeNameButton}
onClick={() => this.submit()}
variant="contained"
color="primary"
disabled={!tagName && !categoryName}
>
Save Tag
</Button>
</div>
);
}
}
const mapDispatchToProps = dispatch => ({
changeUserDisplayName: displayName => dispatch(changeDisplayName(displayName)),
});
const mapStateToProps = state => {
return {
savingDisplayName: state.user.isSavingDisplayName,
newDisplayName: state.user.displayName,
changeDisplayNameErr: state.user.changeDisplayNameErrMsg,
};
};
const enhance = compose(withStyles(styles), connect(mapStateToProps, mapDispatchToProps));
export default enhance(AddTag);

There is prop for this placeholder

Related

How to create dropdown list with description in React

I am trying to create a dropdown list with description in React. For reference you can see the image below:
Is there any other way using bootstrap or Material-UI so I can achieve this?
I am using react-select npm package for dropdown list. you can find live link and code below:
https://codesandbox.io/embed/react-select-selected-option-background-color-forked-jpu99?fontsize=14&hidenavigation=1&theme=dark
const colourOptions = [
{ value: "red", label: "Red" ,description:"Test description for red"},
{ value: "green", label: "Green", description:"Test description for green" },
{ value: "blue", label: "Blue", description:"Test description for blue" }
];
//for styling
const colourStyles = {
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
// const color = chroma(data.color);
console.log({ data, isDisabled, isFocused, isSelected });
return {
...styles,
backgroundColor: isFocused ? "#00A3BE" : "#191D2F",
font: "Segoe UI",
color: "#F9FAFC"
};
}
};
export default () => (
<Select
defaultValue={colourOptions[1]}
label="Single select"
options={colourOptions}
styles={colourStyles}
/>
);
You can override the Option component and provide your own Option that can display both title and description:
import Select, { components } from "react-select";
const colourStyles = {
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
return {
...styles,
backgroundColor: isFocused ? "#00A3BE" : "",
color: isFocused ? "#F9FAFC" : "#191D2F",
display: "flex",
paddingLeft: 0,
"& .left": {
display: "flex",
justifyContent: "center",
width: 60,
marginTop: 3
},
"& .right": {
width: "100%"
},
"& .right > .title": {
display: "block",
margin: "5px 0"
}
};
}
};
const Option = (props) => {
return (
<components.Option {...props}>
<div className="left">{props.isSelected ? "✔" : ""}</div>
<div className="right">
<strong className="title">{props.data.label}</strong>
<div>{props.data.description}</div>
</div>
</components.Option>
);
};
export default () => (
<Select
defaultValue={colourOptions[1]}
label="Single select"
options={colourOptions}
styles={colourStyles}
components={{ Option }}
/>
);
Live Demo

TypeError: theme is undefined - When trying to render Material UI component

I am having trouble rendering my react component since I separated my jss file and changed it from makeStyles to withStyles to avoid a hook problem.
I am getting an error message in my jss styling file as a couple of the methods have a 'theme' in the parenthesis for the styling to work off.
How do I go about changing this so that it renders correctly?
accessControl.component.js
import {connect, useSelector} from "react-redux";
import DataTable from "./userListTable.component";
import {Paper} from "#material-ui/core";
function AdminAccessControl(props) {
const { children, value, index, ...other } = props;
// select user object from redux
const user = useSelector(state => state.user);
// select school object from redux
const school = useSelector(state => state.diveSchool);
const classes = useStyles();
const [role, setRole] = useState({
userRole: "",
});
const handleChange = (property) => (e) => {
setRole({
// override the changed property and keep the rest
...role,
[property]: e.target.value,
});
}
return (
<div className={classes.root}>
<StyledTabs
value={value}
onChange={handleChange}
indicatorColor="primary"
textColor="primary"
aria-label="styled tabs example"
centered>
<StyledTab label="User Access Control" />
{/*<DataTable />*/}
<StyledTab label="Scuba School Access Control" />
{/*<DataTable />*/}
</StyledTabs>
<Typography className={classes.padding} />
</div>
);
}
function mapStateToProps(state){
const { user } = state.auth;
const { school } = state.diveSchool;
return {
user,
school,
};
}
export default compose(
connect(
mapStateToProps,
),
withStyles(useStyles)
)(AdminAccessControl);
myJss-style.js
export const useStyles = (theme) => ({
root: {
flexGrow: 1,
},
padding: {
padding: theme.spacing(3),
},
demo1: {
backgroundColor: theme.palette.background.paper,
},
demo2: {
backgroundColor: '#2e1534',
},
});
export const StyledTabs = () => ({
indicator: {
display: 'flex',
justifyContent: 'center',
backgroundColor: 'transparent',
'& > span': {
maxWidth: 40,
width: '100%',
backgroundColor: '#635ee7',
},
},
})((props) => <StyledTabs {...props} TabIndicatorProps={{ children: <span /> }} />);
export const StyledTab = (theme) => ({
root: {
textTransform: 'none',
color: '#fff',
fontWeight: theme.typography.fontWeightRegular,
fontSize: theme.typography.pxToRem(15),
marginRight: theme.spacing(1),
'&:focus': {
opacity: 1,
},
},
})((props) => <StyledTab disableRipple {...props} />);

How can I create a button to a dialog box inside the PopperComponent of Material UI Labs Autocomplete

I have a Material UI Autocomplete which renders a list of Chips. I have added a button at the bottom of the PopperComponent which when clicked should open a dialog box.
But the Autocomplete doesn't allow the DialogBox to be opened. But the weird part is if I add 'open' to Autocomplete it works.
I have tried adding the onMouseDown event instead of onClick. Also, tried the event.preventDefault(). None of them works. However onMouseDown definitely called my listener for the Dialog box and changed its open state to true, but the dialog box did not appear.
This is the link to the sandbox.
Sandbox to the code
This is the component that implements the Dialog Box.
import React, { useState } from "react";
import { withStyles } from "#material-ui/core/styles";
import Button from "#material-ui/core/Button";
import Dialog from "#material-ui/core/Dialog";
import MuiDialogTitle from "#material-ui/core/DialogTitle";
import MuiDialogContent from "#material-ui/core/DialogContent";
import MuiDialogActions from "#material-ui/core/DialogActions";
import IconButton from "#material-ui/core/IconButton";
import CloseIcon from "#material-ui/icons/Close";
import Typography from "#material-ui/core/Typography";
import { orange } from "#material-ui/core/colors";
const styles = theme => ({
form: {
display: "flex",
flexDirection: "column",
margin: "auto",
width: "fit-content"
},
formControl: {
marginTop: theme.spacing(2),
minWidth: 120
},
formControlLabel: {
marginTop: theme.spacing(1)
},
closeButton: {
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500]
},
selectEmpty: {
marginTop: theme.spacing(2)
},
floatingLabelFocusStyle: {
color: "green"
},
separator: {
marginTop: theme.spacing(1)
},
menuStyle: {
border: "1px solid black",
borderRadius: "5%",
backgroundColor: "lightgrey"
}
});
const DialogTitle = withStyles(styles)(props => {
const { children, classes, onClose, ...other } = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="h6">{children}</Typography>
{onClose ? (
<IconButton
aria-label="close"
className={classes.closeButton}
onClick={onClose}
>
<CloseIcon />
</IconButton>
) : null}{" "}
</MuiDialogTitle>
);
});
const DialogContent = withStyles(theme => ({
root: {
padding: theme.spacing(2)
}
}))(MuiDialogContent);
const DialogActions = withStyles(theme => ({
root: {
margin: 0,
padding: theme.spacing(1)
}
}))(MuiDialogActions);
const ActionButton = withStyles(theme => ({
root: {
color: "#E87424",
backgroundColor: "white",
"&:hover": {
backgroundColor: orange[100]
}
}
}))(Button);
const ManageTagButton = withStyles(theme => ({
root: {
color: "#E87424"
}
}))(Button);
const TagContainer = props => {
const [open, setOpen] = useState(false);
const handleClickOpen = () => {
console.log("Dialog box clicked");
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<ManageTagButton
onMouseDown={event => {
event.preventDefault();
handleClickOpen();
}}
size="small"
>
MANAGE TAGS
</ManageTagButton>
<Dialog
fullWidth
maxWidth={"sm"}
onClose={handleClose}
aria-labelledby="customized-dialog-title"
open={open}
>
<DialogTitle id="customized-dialog-title">Manage Tags</DialogTitle>
<DialogContent dividers>
<h1>
This is the component of the dialog box. In reality I neeed to
display a data table with CRUD operations to add more tags.
</h1>
</DialogContent>
<DialogActions>
<ActionButton autoFocus onClick={handleClose} color="secondary">
CLOSE
</ActionButton>
</DialogActions>
</Dialog>
</div>
);
};
export default TagContainer;
This is the component that implements the Autocomplete.
import React, { Fragment } from "react";
import Chip from "#material-ui/core/Chip";
import Autocomplete from "#material-ui/lab/Autocomplete";
import { withStyles } from "#material-ui/core/styles";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemText from "#material-ui/core/ListItemText";
import ListItemSecondaryAction from "#material-ui/core/ListItemSecondaryAction";
import Paper from "#material-ui/core/Paper";
import TagContainer from "./TagContainer";
const ListItemCustom = withStyles(theme => ({
gutters: {
paddingLeft: 0,
paddingRight: 0
},
secondaryAction: {
paddingRight: 0
}
}))(ListItem);
const AutocompleteCustom = withStyles(theme => ({
endAdornment: {
display: "none"
}
}))(Autocomplete);
const CreateButton = withStyles(theme => ({
root: {
color: "#E87424"
}
}))(Button);
const MuiFilledInputCustom = makeStyles(
{
underline: {
"&&&:before": {
borderBottom: "none"
},
"&&:after": {
borderBottom: "none"
}
}
},
{ name: "MuiFilledInput" }
);
const loadCustomStyles = () => {
MuiFilledInputCustom();
};
export default function AddTagToThread() {
loadCustomStyles();
const handleSubmit = () => {
console.log("Add tags to thread");
};
const useStyles = makeStyles({
root: {
minWidth: 300,
width: 300,
height: 250,
minHeight: 250,
zIndex: 1
},
buttons: {
display: "flex",
justifyContent: "flex-end"
}
});
const PaperComponentCustom = options => {
const classes = useStyles();
const { containerProps, children } = options;
return (
<Paper className={classes.root} {...containerProps} square>
{children}
<div className={classes.buttons}>
<TagContainer />
</div>
</Paper>
);
};
return (
<List dense={false}>
<ListItemCustom>
<ListItemText>
<AutocompleteCustom
multiple
id="size-small-filled-multi"
size="medium"
options={tagList}
noOptionsText="No options"
freeSolo
filterSelectedOptions
PaperComponent={PaperComponentCustom}
getOptionLabel={option => option.name}
onChange={(event, value) => {
console.log(value);
}}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
variant="default"
style={{
backgroundColor: option.color
}}
label={option.name}
size="medium"
{...getTagProps({ index })}
/>
))
}
renderOption={option => (
<Fragment>
<Chip
variant="default"
style={{
backgroundColor: option.color,
padding: "15px",
marginLeft: "12px"
}}
label={option.name}
size="medium"
/>
</Fragment>
)}
renderInput={params => (
<TextField
{...params}
variant="filled"
label="Filter By Tag"
placeholder="Select Tag"
/>
)}
/>
</ListItemText>
<ListItemSecondaryAction>
<CreateButton onClick={handleSubmit}>ADD TAG</CreateButton>
</ListItemSecondaryAction>
</ListItemCustom>
</List>
);
}
const tagList = [
{ name: "Follow Up", tagId: 1, color: "#FFC107" },
{ name: "Important", tagId: 2, color: "#46B978" },
{ name: "Idea", tagId: 3, color: "#EEA5F6" },
{ name: "Non Issue", tagId: 4, color: "#2EACE2" }
];
I have been stuck at this for last couple of days. Any help is greatly appreciated.
The issue with your code is that the <Dialog/> component is in the PaperComponentCustom component which gets unmounted after the option is selected.
<Paper className={classes.root} {...containerProps} square>
{children}
<ManageTagButton onMouseDown={handleClickOpen} fullWidth>
MANAGE TAGS
</ManageTagButton>
</Paper>
The solution to keep only the <ManageTagButton/> component in the PaperComponentCustom and move the <Dialog/> component one level up. I imagine that even if you have 10 elements in the <List/> you would still have only one <Dialog>, you cannot have 10 dialog components opened at once.
So therefore your <AddTagToThread/> component should render the dialog directly and the state of the dialog open and the handlers handleOpen and handleClose should be moved in the <AddTagToThread/> component also
Working codesandbox HERE, code below
Autocomplete component
import React, { Fragment, useState } from "react";
import Chip from "#material-ui/core/Chip";
import Autocomplete from "#material-ui/lab/Autocomplete";
import { withStyles } from "#material-ui/core/styles";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemText from "#material-ui/core/ListItemText";
import ListItemSecondaryAction from "#material-ui/core/ListItemSecondaryAction";
import Paper from "#material-ui/core/Paper";
import TagContainer from "./TagContainer";
const ListItemCustom = withStyles(theme => ({
gutters: {
paddingLeft: 0,
paddingRight: 0
},
secondaryAction: {
paddingRight: 0
}
}))(ListItem);
const AutocompleteCustom = withStyles(theme => ({
endAdornment: {
display: "none"
}
}))(Autocomplete);
const CreateButton = withStyles(theme => ({
root: {
color: "#E87424"
}
}))(Button);
const MuiFilledInputCustom = makeStyles(
{
underline: {
"&&&:before": {
borderBottom: "none"
},
"&&:after": {
borderBottom: "none"
}
}
},
{ name: "MuiFilledInput" }
);
const loadCustomStyles = () => {
MuiFilledInputCustom();
};
const ManageTagButton = withStyles(theme => ({
root: {
color: "#E87424"
}
}))(Button);
export default function AddTagToThread() {
loadCustomStyles();
const handleSubmit = () => {
console.log("Add tags to thread");
};
const [open, setOpen] = useState(false);
const handleClickOpen = () => {
console.log("Dialog box clicked");
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const useStyles = makeStyles({
root: {
minWidth: 300,
width: 300,
height: 250,
minHeight: 250,
zIndex: 1
},
buttons: {
display: "flex",
justifyContent: "flex-end"
}
});
const PaperComponentCustom = options => {
const classes = useStyles();
const { containerProps, children } = options;
return (
<Paper className={classes.root} {...containerProps} square>
{children}
<ManageTagButton onMouseDown={handleClickOpen} fullWidth>
MANAGE TAGS
</ManageTagButton>
</Paper>
);
};
return (
<>
<TagContainer open={open} handleClose={handleClose} />
<List dense={false}>
<ListItemCustom>
<ListItemText>
<AutocompleteCustom
multiple
id="size-small-filled-multi"
size="medium"
options={tagList}
noOptionsText="No options"
freeSolo
filterSelectedOptions
PaperComponent={PaperComponentCustom}
getOptionLabel={option => option.name}
onChange={(event, value) => {
console.log(value);
}}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
variant="default"
style={{
backgroundColor: option.color
}}
label={option.name}
size="medium"
{...getTagProps({ index })}
/>
))
}
renderOption={option => (
<Fragment>
<Chip
variant="default"
style={{
backgroundColor: option.color,
padding: "15px",
marginLeft: "12px"
}}
label={option.name}
size="medium"
/>
</Fragment>
)}
renderInput={params => (
<TextField
{...params}
variant="filled"
label="Filter By Tag"
placeholder="Select Tag"
/>
)}
/>
</ListItemText>
<ListItemSecondaryAction>
<CreateButton onClick={handleSubmit}>ADD TAG</CreateButton>
</ListItemSecondaryAction>
</ListItemCustom>
</List>
</>
);
}
const tagList = [
{ name: "Follow Up", tagId: 1, color: "#FFC107" },
{ name: "Important", tagId: 2, color: "#46B978" },
{ name: "Idea", tagId: 3, color: "#EEA5F6" },
{ name: "Non Issue", tagId: 4, color: "#2EACE2" }
];
Dialog component
import React, { useState } from "react";
import { withStyles } from "#material-ui/core/styles";
import Button from "#material-ui/core/Button";
import Dialog from "#material-ui/core/Dialog";
import MuiDialogTitle from "#material-ui/core/DialogTitle";
import MuiDialogContent from "#material-ui/core/DialogContent";
import MuiDialogActions from "#material-ui/core/DialogActions";
import IconButton from "#material-ui/core/IconButton";
import CloseIcon from "#material-ui/icons/Close";
import Typography from "#material-ui/core/Typography";
import { orange } from "#material-ui/core/colors";
const styles = theme => ({
form: {
display: "flex",
flexDirection: "column",
margin: "auto",
width: "fit-content"
},
formControl: {
marginTop: theme.spacing(2),
minWidth: 120
},
formControlLabel: {
marginTop: theme.spacing(1)
},
closeButton: {
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500]
},
selectEmpty: {
marginTop: theme.spacing(2)
},
floatingLabelFocusStyle: {
color: "green"
},
separator: {
marginTop: theme.spacing(1)
},
menuStyle: {
border: "1px solid black",
borderRadius: "5%",
backgroundColor: "lightgrey"
}
});
const DialogTitle = withStyles(styles)(props => {
const { children, classes, onClose, ...other } = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="h6">{children}</Typography>
{onClose ? (
<IconButton
aria-label="close"
className={classes.closeButton}
onClick={onClose}
>
<CloseIcon />
</IconButton>
) : null}{" "}
</MuiDialogTitle>
);
});
const DialogContent = withStyles(theme => ({
root: {
padding: theme.spacing(2)
}
}))(MuiDialogContent);
const DialogActions = withStyles(theme => ({
root: {
margin: 0,
padding: theme.spacing(1)
}
}))(MuiDialogActions);
const ActionButton = withStyles(theme => ({
root: {
color: "#E87424",
backgroundColor: "white",
"&:hover": {
backgroundColor: orange[100]
}
}
}))(Button);
const TagContainer = ({ open, handleClose }) => {
return (
<Dialog
fullWidth
maxWidth={"sm"}
onClose={handleClose}
aria-labelledby="customized-dialog-title"
open={open}
>
<DialogTitle id="customized-dialog-title">Manage Tags</DialogTitle>
<DialogContent dividers>
<h1>
This is the component of the dialog box. In reality I neeed to display
a data table with CRUD operations to add more tags.
</h1>
</DialogContent>
<DialogActions>
<ActionButton autoFocus onClick={handleClose} color="secondary">
CLOSE
</ActionButton>
</DialogActions>
</Dialog>
);
};
export default TagContainer;

react-autosuggest how to style input and autosuggestion when using along with Material-ui

I am using react-autosuggest in my Material-UI component to get suggestions when user types. And just not able to style the input field and the suggestions text.
Probably I am missing something basic here, and any guidance will be immensly helpful. The official dox of react-autosuggest is here for using the theme technique that uses react-themeable. But I could not implement that in my Material-UI component.
The below is my code that I am trying with.
import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import { makeStyles } from '#material-ui/core/styles'
import Autosuggest from 'react-autosuggest';
import { defaultTheme } from 'react-autosuggest/dist/theme';
const useStyles = makeStyles(theme => ({
container: {
margin: 'auto',
backgroundColor: theme.background.default,
},
innerTableContainer: {
height: 'calc(100vh - 190px)',
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.background.paper,
},
react_autosuggest__container: {
"position": "relative",
"width": "440px",
},
react_autosuggest__input: {
"width": "240px",
"height": "30px",
"padding": "10px 20px",
"fontFamily": "Helvetica, sans-serif",
"fontWeight": "300",
"fontSize": "16px",
"border": "1px solid #aaa",
"borderRadius": "4px"
},
react_autosuggest__input__focused: {
"outline": "none"
},
react_autosuggest__input__open: {
"borderBottomLeftRadius": "0",
"borderBottomRightRadius": "0"
},
react_autosuggest__suggestions_container__open: {
"display": "block",
"position": "absolute",
"top": "51px",
"width": "280px",
"border": "1px solid #aaa",
"backgroundColor": "#fff",
"fontFamily": "Helvetica, sans-serif",
"fontWeight": "300",
"fontSize": "16px",
"borderBottomLeftRadius": "4px",
"borderBottomRightRadius": "4px",
"zIndex": "2"
},
react_autosuggest__suggestions_list: {
"margin": "0",
"padding": "0",
"listStyleType": "none"
},
react_autosuggest__suggestion: {
"cursor": "pointer",
"padding": "10px 20px"
},
react_autosuggest__suggestion__highlighted: {
"backgroundColor": "#ddd"
}
}))
const GithubMostPopularList = () => {
const classes = useStyles()
const [value, setValue] = useState('')
const [suggestions, setSuggestions] = useState([])
const onChange = (event, { newValue, method }) => {
setValue(newValue)
};
const onSuggestionsFetchRequested = ({ value }) => {
setSuggestions(getSuggestions(value))
};
const onSuggestionsClearRequested = () => {
setSuggestions([])
};
const inputProps = {
placeholder: "Start typing your city name",
value,
onChange: onChange,
};
return (
<div className={classes.container}>
<div className={classes.react_autosuggest__container} >
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
/>
</div>
)}
</div>
)
}
export default GithubMostPopularList
I have also tried this solution given in one of Github issue
<Autosuggest
//misc extra props I've cut out for brevity
theme={{
...defaultTheme,
...{
container: {
...defaultTheme.container,
display: 'visible',
width: '340px',
},
//more overrides
}
}}
/>
But in this case the component is not compiling at all.
Answering my own question.
I was able to solve it as below, the useStyles = makeStyles() portion remains the same and the below is how to change the defulat theme of react-autosuggest.
import { defaultTheme } from 'react-autosuggest/dist/theme';
....
....
const GithubMostPopularList = () => {
.....
.....
return (
<div className={classes.container}>
{console.log('GITHUB USER ', JSON.stringify(globalStore.githubUser))}
<div className={classes.tableAndFabContainer}>
{globalStore.loading ? (
<div className={classes.spinner}>
<LoadingSpinner />
</div>
) : (
<div className={classes.table}>
{console.log('VALUE IS ', value)}
<div className={classes.inputandButtonContainer} >
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
theme={{
...defaultTheme,
container: classes.react_autosuggest__container,
input: classes.react_autosuggest__input,
inputOpen: classes.react_autosuggest__input__open,
inputFocused: classes.react_autosuggest__input__focused,
suggestionsContainer: classes.react_autosuggest__suggestions_container,
suggestionsContainerOpen: classes.react_autosuggest__suggestions_container__open,
suggestionsList: classes.react_autosuggest__suggestions_list,
suggestion: classes.react_autosuggest__suggestion,
suggestionHighlighted: classes.react_autosuggest__suggestion__highlighted,
}
}
/>
</div>
</div>
)}
</div>
</div>
)
}
export default GithubMostPopularList
Not sure about what you did. This is what I did, and it works well :
One component with the definition of your styling, and the Autosuggest component you render :
import { makeStyles } from '#material-ui/styles';
const useStyles = makeStyles({
container: {
position: "relative",
},
input: {
width: "240px",
height: "30px",
width: '80%',
padding: "10px 20px",
fontFamily: "Helvetica, sans-serif",
fontWeight: "bold",
fontSize: "16px",
border: "1px solid #aaa",
borderRadius: "4px"
},
inputFocused: {
outlineStyle: "none"
}
// add other styling here...
});
const MyAutosuggest = (props) => {
const inputProps = {
placeholder: 'Type a programming language',
value: props.value,
onChange: props.onChange
};
const theme = useStyles();
return(
<Autosuggest
suggestions={props.suggestions}
onSuggestionsFetchRequested={props.onSuggestionsFetchRequested}
onSuggestionsClearRequested={props.onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
theme={theme}
/>
)
}
I import MyAutosuggest in the component where I implement autosuggest :
import MyAutosuggest from './Autosuggest';
<MyAutosuggest
value={this.state.value}
onChange={this.onChange}
suggestions={this.state.suggestions}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
/>

Any React Tags Input Component where tags can be edited?

I have been looking everywhere but i didn't seem to find any component that allows a tag to be editable. currently i am using
https://github.com/JedWatson/react-select
and here is my code:
<CreatableSelect
styles={{
multiValueLabel: (provided, state) => ({
...provided,
whiteSpace: "normal"
})
}}
cropWithEllipsis={false}
components={components}
inputValue={inputValue}
isClearable={false}
isMulti
menuIsOpen={false}
onChange={this.handleChange}
onInputChange={this.handleInputChange}
onBlur={this.handleBlur}
onKeyDown={this.handleKeyDown}
value={value}
className={styles.questionInput}
onValueClick={this.onValueClick}
/>
but it doesn't have any props or method to edit a tag just delete. onValueClick does not do anything.
i found this:
https://goodies.pixabay.com/jquery/tag-editor/demo.html
but since i am new to react/typescript i dont know how to implement this to my React Typescript project.
Thank you for your help.
Nevermind looking for a component. i found this online, doesnt have an edit functionality but you can get the item onfocus so i tried modifying it.
https://codepen.io/srph/pen/WrPywK
class TagInput extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
focused: false,
input: ''
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleInputKeyDown = this.handleInputKeyDown.bind(this);
this.handleRemoveItem = this.handleRemoveItem.bind(this);
}
render() {
const styles = {
container: {
border: '1px solid #ddd',
padding: '5px',
borderRadius: '5px',
},
items: {
display: 'inline-block',
padding: '2px',
border: '1px solid blue',
fontFamily: 'Helvetica, sans-serif',
borderRadius: '5px',
marginRight: '5px',
cursor: 'pointer'
},
input: {
outline: 'none',
border: 'none',
fontSize: '14px',
fontFamily: 'Helvetica, sans-serif'
}
};
return (
<label>
<ul style={styles.container}>
{this.state.items.map((item, i) =>
<li key={i} style={styles.items} onClick={this.handleRemoveItem(i)}>
{item}
<span>(x)</span>
</li>
)}
<input
style={styles.input}
value={this.state.input}
onChange={this.handleInputChange}
onKeyDown={this.handleInputKeyDown} />
</ul>
</label>
);
}
handleInputChange(evt) {
this.setState({ input: evt.target.value });
}
handleInputKeyDown(evt) {
if ( evt.keyCode === 13 ) {
const {value} = evt.target;
this.setState(state => ({
items: [...state.items, value],
input: ''
}));
}
if ( this.state.items.length && evt.keyCode === 8 && !this.state.input.length ) {
this.setState(state => ({
items: state.items.slice(0, state.items.length - 1)
}));
}
}
handleRemoveItem(index) {
return () => {
this.setState(state => ({
items: state.items.filter((item, i) => i !== index)
}));
}
}
}
ReactDOM.render(
<TagInput />,
document.getElementById('app')
);
so recreated it to suit my needs:
https://codesandbox.io/s/n03r8w74m

Resources