Material UI v1 Autocomplete样式定制与Props传递技术咨询
Customizing Material UI v1 Autocomplete (with react-autosuggest) & Passing Props to Styles
Hey there! Let's break down how to solve your styling and prop-passing needs for this Autocomplete setup:
1. Customizing the Floating Label (the label that moves up when input has content)
When the input has content or is focused, the label shifts up into a "shrunk" state. We can target this state directly with a custom class:
- Add a new class in your
stylesobject to define the shrunk label's appearance:labelShrink: { color: 'yellow', // Your desired color for the elevated label fontWeight: 600 // Optional: adjust weight for emphasis } - Update the
renderInputfunction to apply this class viaInputLabelProps:function renderInput(inputProps) { const { classes, autoFocus, value, ref, ...other } = inputProps; return ( <TextField autoFocus={autoFocus} className={classes.textField} value={value} inputRef={ref} label="Country" InputLabelProps={{ classes: { shrink: classes.labelShrink } }} InputProps={{ classes: { input: classes.input, // We'll add underline styles here next }, ...other, }} /> ); }
2. Customizing the Input Underline
To style the input's underline (including hover and focused states), use the dedicated classes for underline in InputProps:
- Add these classes to your
stylesobject:underlineRoot: { // Default underline color '&:before': { borderBottomColor: '#ccc' } }, underlineHover: { // Underline color when hovering '&:hover:not($underlineFocused):before': { borderBottomColor: '#888' } }, underlineFocused: { // Underline color when input is focused '&:after': { borderBottomColor: 'yellow' } } - Apply these classes to the
InputPropsof your TextField:InputProps={{ classes: { input: classes.input, underline: classes.underlineRoot, hover: classes.underlineHover, focused: classes.underlineFocused }, ...other, }}
3. Passing Props to the Styles Function
The withStyles HOC lets your styles function accept component props as a second argument, enabling dynamic styling based on props passed to your component:
- Modify your
stylesfunction to acceptpropsand use them in your styles:const styles = (theme, props) => ({ // ... existing classes labelShrink: { color: props.labelColor || 'yellow', // Use prop value or fallback to yellow fontWeight: 600 }, underlineFocused: { '&:after': { borderBottomColor: props.underlineColor || 'yellow' } } }); - Update your component's propTypes to include the new props:
IntegrationAutosuggest.propTypes = { classes: PropTypes.object.isRequired, labelColor: PropTypes.string, underlineColor: PropTypes.string }; - Now you can pass these props when using your component:
<IntegrationAutosuggest labelColor="orange" underlineColor="blue" />
Full Modified Code
Here's the complete code with all the above changes applied:
import React from 'react'; import PropTypes from 'prop-types'; import Autosuggest from 'react-autosuggest'; import match from 'autosuggest-highlight/match'; import parse from 'autosuggest-highlight/parse'; import TextField from 'material-ui/TextField'; import Paper from 'material-ui/Paper'; import { MenuItem } from 'material-ui/Menu'; import { withStyles } from 'material-ui/styles'; const suggestions = [ { label: 'Afghanistan' }, { label: 'Aland Islands' }, { label: 'Albania' }, { label: 'Algeria' }, { label: 'American Samoa' }, { label: 'Andorra' }, { label: 'Angola' }, { label: 'Anguilla' }, { label: 'Antarctica' }, { label: 'Antigua and Barbuda' }, { label: 'Argentina' }, { label: 'Armenia' }, { label: 'Aruba' }, { label: 'Australia' }, { label: 'Austria' }, { label: 'Azerbaijan' }, { label: 'Bahamas' }, { label: 'Bahrain' }, { label: 'Bangladesh' }, { label: 'Barbados' }, { label: 'Belarus' }, { label: 'Belgium' }, { label: 'Belize' }, { label: 'Benin' }, { label: 'Bermuda' }, { label: 'Bhutan' }, { label: 'Bolivia, Plurinational State of' }, { label: 'Bonaire, Sint Eustatius and Saba' }, { label: 'Bosnia and Herzegovina' }, { label: 'Botswana' }, { label: 'Bouvet Island' }, { label: 'Brazil' }, { label: 'British Indian Ocean Territory' }, { label: 'Brunei Darussalam' }, ]; function renderInput(inputProps) { const { classes, autoFocus, value, ref, ...other } = inputProps; return ( <TextField autoFocus={autoFocus} className={classes.textField} value={value} inputRef={ref} label="Country" InputLabelProps={{ classes: { shrink: classes.labelShrink } }} InputProps={{ classes: { input: classes.input, underline: classes.underlineRoot, hover: classes.underlineHover, focused: classes.underlineFocused }, ...other, }} /> ); } function renderSuggestion(suggestion, { query, isHighlighted }) { const matches = match(suggestion.label, query); const parts = parse(suggestion.label, matches); return ( <MenuItem selected={isHighlighted} component="div"> <div> {parts.map((part, index) => { return part.highlight ? ( <span key={String(index)} style={{ fontWeight: 300 }}> {part.text} </span> ) : ( <strong key={String(index)} style={{ fontWeight: 500 }}> {part.text} </strong> ); })} </div> </MenuItem> ); } function renderSuggestionsContainer(options) { const { containerProps, children } = options; return ( <Paper {...containerProps} square> {children} </Paper> ); } function getSuggestionValue(suggestion) { return suggestion.label; } function getSuggestions(value) { const inputValue = value.trim().toLowerCase(); const inputLength = inputValue.length; let count = 0; return inputLength === 0 ? [] : suggestions.filter(suggestion => { const keep = count < 5 && suggestion.label.toLowerCase().slice(0, inputLength) === inputValue; if (keep) { count += 1; } return keep; }); } const styles = (theme, props) => ({ container: { flexGrow: 1, position: 'relative', height: 200, }, suggestionsContainerOpen: { position: 'absolute', marginTop: theme.spacing.unit, marginBottom: theme.spacing.unit * 3, left: 0, right: 0, }, suggestion: { display: 'block', }, suggestionsList: { margin: 0, padding: 0, listStyleType: 'none', }, textField: { width: '100%', }, labelShrink: { color: props.labelColor || 'yellow', fontWeight: 600 }, underlineRoot: { '&:before': { borderBottomColor: '#ccc' } }, underlineHover: { '&:hover:not($underlineFocused):before': { borderBottomColor: '#888' } }, underlineFocused: { '&:after': { borderBottomColor: props.underlineColor || 'yellow' } } }); class IntegrationAutosuggest extends React.Component { state = { value: '', suggestions: [], }; handleSuggestionsFetchRequested = ({ value }) => { this.setState({ suggestions: getSuggestions(value), }); }; handleSuggestionsClearRequested = () => { this.setState({ suggestions: [], }); }; handleChange = (event, { newValue }) => { this.setState({ value: newValue, }); }; render() { const { classes } = this.props; return ( <Autosuggest theme={{ container: classes.container, suggestionsContainerOpen: classes.suggestionsContainerOpen, suggestionsList: classes.suggestionsList, suggestion: classes.suggestion, }} renderInputComponent={renderInput} suggestions={this.state.suggestions} onSuggestionsFetchRequested={this.handleSuggestionsFetchRequested} onSuggestionsClearRequested={this.handleSuggestionsClearRequested} renderSuggestionsContainer={renderSuggestionsContainer} getSuggestionValue={getSuggestionValue} renderSuggestion={renderSuggestion} inputProps={{ autoFocus: true, classes, placeholder: 'Search a country (start with a)', value: this.state.value, onChange: this.handleChange, }} /> ); } } IntegrationAutosuggest.propTypes = { classes: PropTypes.object.isRequired, labelColor: PropTypes.string, underlineColor: PropTypes.string }; export default withStyles(styles)(IntegrationAutosuggest);
内容的提问来源于stack exchange,提问作者Patrickkx
相关产品推荐
相关产品推荐

