You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 styles object 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 renderInput function to apply this class via InputLabelProps:
    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 styles object:
    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 InputProps of 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 styles function to accept props and 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:50:06