Search code examples
javascriptcssreactjsreact-selectreact-state

Keeping placeholder on react-select


I have tried everything I can think of, but I cannot prevent the placeholder in react-select from disappearing (I assume changed to display: none because it is no longer in the HTML) when a value is selected for the component.

I've read through both posts with similar issues: https://github.com/JedWatson/react-select/issues/2152 https://github.com/JedWatson/react-select/issues/2143

But haven't found any success

My Styling on the placeholder element is:

valueContainer: base => ({
        overflow: 'visible'
      }),
placeholder: (provided, state) => ({
        ...provided,
        position: "absolute",
        marginTop: '-30px',
        display: 
      state.isFocused || state.isSelected || state.selectProps.inputValue || state.value
      ? 'block'
      : 'block',
      }),

Here is a stackblitz. The end goal is to start the placeholder in the center and move it up to the spot it is here on focus and selection. The problem is, once something is selected, the placeholder disappears. https://stackblitz.com/edit/react-egf4va


Solution

  • You need to create a custom ValueContainer, and return the Placeholder in it. Then pass it in property components on the Select component:

    import React, { Component } from 'react';
    
    import { render } from 'react-dom';
    import Select, {components} from 'react-select';
    import Hello from './Hello';
    import './style.css';
    const { ValueContainer, Placeholder } = components;
    
    const CustomValueContainer = ({ children, ...props }) => {
      return (
        <ValueContainer {...props}>
          <Placeholder {...props} isFocused={props.isFocused}>
            {props.selectProps.placeholder}
          </Placeholder>
          {React.Children.map(children, child =>
            child && child.type !== Placeholder ? child : null
          )}
        </ValueContainer>
      );
    };
    class App extends Component {
      constructor() {
        super();
        this.state = {
          name: 'React'
        };
      }
    
      render() {
        const customStyles = {
          container: base => ({
            ...base,
            width: '100%',
          }),
          control: base => ({
            ...base,
            border: 0,
            // This line disable the blue border
            boxShadow: 'none',
            height: '42px',
            borderRadius: '6px'
          }),
          valueContainer: base => ({
            ...base,
            fontSize: '15px',
            top: '3.5px',
            marginLeft: '4px',
            overflow: 'visible'
          }),
          placeholder: base => ({
            ...base,
            fontStyle: 'italic',
            marginTop: '20px',
            position: 'absolute',
          })
        }
        const options = [
         { value: 'chocolate', label: 'Chocolate' },
         { value: 'strawberry', label: 'Strawberry' },
         { value: 'vanilla', label: 'Vanilla' }
       ];
        return (
    
          <div>
            <Select components={{ValueContainer: CustomValueContainer}}
            options={options} placeholder="Select" isClearable="true" styles={customStyles} className="react-select" classNamePrefix="react-select"/>
          </div>
        );
      }
    }
    
    render(<App />, document.getElementById('root'));