Populate react-select with image

51.1k views Asked by At

How do I pass options to preview images in select. I have country select and I would like to preview country flags. I don't know how to pass the "options" object in this case.

    var countries = 
    [
          {value: 'me', label: 'Montenegro'},
          {value:'rs',label: 'Serbia' }
    ];

   <Select name={"nationality_" + passenger.passengerId}
           value={passenger.nationality}
           options={countries}/>   
7

There are 7 answers

2
Nafiul Islam On

I think you're wanting your select to behave like last but one (Custom Placeholder, Option, Value, and Arrow Components) in this demo. Click here to find out the way they've designed their ones for demo

0
only_one On

In my case, when I want to render Country flags, I just add third value to single options, look below:

var countries = 
[
      {value: 'me', label: 'Montenegro', flagPath: <relative-path-to-flag>},
      {value:'rs',label: 'Serbia', flagPath: <relative-path-to-flag> }
];

And if You want to render flag in dropdown options use 'component.Option', but it wouldn't display flag in selected option, for this you have to use 'component.SingleValue', for example:

singleOption = (props: OptionProps<any>) => (
<components.Option {...props}>
  {props.data.flagPath? DO SOMETHING WITH YOUR ICON HERE : null}
  {props.label}
</components.Option>)


singleValue = (props: any) => (
<components.SingleValue {...props}>
  {props.data.flagPath?DO SOMETHING WITH YOUR ICON HERE: null}
</components.SingleValue>

)

Then You must use components inside Select, like this:

<Select
      ...
      components={{ 
        Option: this.singleOption, 
        SingleValue: this.singleValue
      }}
    />

Hope it will help someone to resolve this problem :)

0
Angoose On

This may not be the best solution for everybody, but it was the best for me. I was trying to figure out how to do this and this post was great a help. Props to Canda.

Explanation/Steps

1. Define your options as normal, but add an extra key, called image. This should contain an image URL.

2. Modify the react-select components so that both selected and non-selected options will have images next to them.

3. Add some custom styles to the components to ensure the images are displayed properly.

4. Use the Select component with some awesome images!

Final Code

// Step 1
const options = [
    {
        label: 'Option 1',
        value: 0,
        image: 'https://example.com/amazing-image-1.png',
    },
    {
        label: 'Option 2',
        value: 1,
        image: 'https://example.com/amazing-image-2.png',
    }
];

// Step 2
import { components } from 'react-select';
const { SingleValue, Option } = components;

const IconSingleValue = (props) => (
    <SingleValue {...props}>
        <img src={props.data.image} style={{ height: '30px', width: '30px', borderRadius: '50%', marginRight: '10px' }}/>
        {props.data.label}
    </SingleValue>
);

const IconOption = (props) => (
    <Option {...props}>
        <img src={props.data.image} style={{ height: '30px', width: '30px', borderRadius: '50%', marginRight: '10px' }}/>
        {props.data.label}
    </Option>
);

// Step 3
const customStyles = {
    option: (provided) => ({
        ...provided,
        display: 'flex',
        flexDirection: 'row',
        alignItems: 'center',
    }),
    singleValue: (provided) => ({
        ...provided,
        display: 'flex',
        flexDirection: 'row',
        alignItems: 'center',
    }),
}

// Step 4
import Select from 'react-select';

[...]
    <Select
        styles={customStyles}
        components={SingleValue: IconSingleValue, Option: IconOption }
        options={options}
    />
[...]

I'm by no means an expert with this library. I just wanted to share what I found to be a pretty simple solution to what seems to be a common problem. If something can be done better, please let me know.

0
Max Vasyliev On

formatOptionLabel - Worked for me.

<ReactSelect
  name={'logo_' + attributes.option_id}
  value={options.filter(obj => selectedValue.value === obj.value)}
  formatOptionLabel={option => (
                    <div>
                        {option.image ? <img src={option.image} /> : ''}
                        <span>{option.label}</span>
                    </div>
                )}
/>  
2
Ezeifejafor Dominic On

Please note the following:

  1. I am using chakra UI for my styling

  2. This is a Next project

  3. My images are stored as exportable SVG components e.g

    export const YoutubeIcon = (props: any) => {
      return (
        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 12" {...props}>
          <path fill="#ED1D24" d="M15.67 2.14A2 2 0 0 0 14.25.72C13 .38 8 .38 8 .38s-5 0-6.25.34A2 2 0 0 0 .33 2.14C0 3.39 0 6 0 6s0 2.61.33 3.86a2 2 0 0 0 1.42 1.42c1.25.34 6.25.34 6.25.34s5 0 6.25-.34a2 2 0 0 0 1.42-1.42C16 8.61 16 6 16 6s0-2.61-.33-3.86Z"/>
          <path fill="#fff" d="M6.36 8.37 10.55 6 6.36 3.63v4.74Z"/>
        </svg>
      )
    }

STEP 1: List with the data to be used by your select

export const socials = [
  {
    title: 'Youtube',
    value: 'youtube',
    icon: YoutubeIcon
  },
  {
    title: 'Discord',
    value: 'discord',
    icon: DiscordIcon
  },
  {
    title: 'Facebook',
    value: 'facebook',
    icon: FbIcon
  },
  {
    title: 'Twitter',
    value: 'twitter',
    icon: TwitterIcon
  },
];

STEP 2: Map the list of the previous step into HTML

const social = socials.map(socialChannels => ({
    value: socialChannels.value.toLowerCase(),
    label: (
      <Flex alignItems='center' gap='0.5rem'>
        <Box width='1rem'>{socialChannels.icon && <socialChannels.icon />}</Box>
        <Text>{socialChannels.title}</Text>
      </Flex>
    ),
  }));

STEP 3: Create your select and add the HTML object you created previously

<Select options={social}
   name='eventPlatform'
   id='eventPlatform'
   components={{ IndicatorSeparator: () => null }}
/>
2
GG. On

Gaurav's answer works but you lose the ability to search an option by its label.

Instead, use the prop formatOptionLabel which allows you to change the default format:

const countries = [
  { value: 'me', label: 'Montenegro', image: '…' },
  { value:'rs', label: 'Serbia', image: '…' }
];

<ReactSelect
  value={passenger.nationality}
  options={countries}
  formatOptionLabel={country => (
    <div className="country-option">
      <img src={country.image} alt="country-image" />
      <span>{country.label}</span>
    </div>
  )}
/>  

From the doc:

formatOptionLabel

Formats option labels in the menu and control as React components

https://react-select.com/props#select-props

3
Gaurav Tanwar On

Change the label in countries to html.

const options = [
    { value: 'chocolate', label: <div><img src={copyIcon} height="30px" width="30px"/>Chocolate </div> },
    { value: 'strawberry', label: 'Strawberry' },
    { value: 'vanilla', label: 'Vanilla' },
  ];

Like this add this will add image in options for select.