user3657538
user3657538

Reputation: 215

material ui autoComplete with icons

Hi I am trying to implement material UI autocomplete dropbox with an icon next to the displayed text. my implementation is working, but when I select one of the options its not being displayed. The problem is with this part of the code:

renderInput={params => (
                        <Fragment>
                            <TextField
                                {...params}
                                variant="outlined"
                                label="Select Account"
                                placeholder="Favorites"
                                margin="normal"
                                fullWidth
                            />
                        </Fragment>

                    )}

if I remove he icon rendering from getOptionLabel then when selecting the selected text show just fine. any help would be very much appreciated. right now the result of this code looks like: enter image description here

import React, { Fragment, useState } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import {makeStyles} from "@material-ui/core";
import Autocomplete from "@material-ui/lab/Autocomplete/Autocomplete";
import TextField from "@material-ui/core/TextField";
import FacebookIcon from '@material-ui/icons/Facebook';
import AppleIcon from '@material-ui/icons/Apple';
import IconButton from "@material-ui/core/IconButton";


const useStyles = makeStyles(theme => ({
    Select: {
        width: 425,
    },
    icon: {
        color: '#0095e2'
    },
}));

const SelectAccount = ({ clientAccountsData, accountSelected }) => {
    const accountSelectedHandler = async (event, values) => {
        if ( values !== null )
        {
            accountSelected(values);
        }
        else {
            accountSelected('');
        }
    };

    const renderCorrectAccountChannelIcon = (network_id) => {
        if ( network_id=== '1' )
        {
            return (
                <FacebookIcon/>
            );
        }
        else if ( network_id=== '2' )
        {
            return (
                <img
                    src={'/Icons/snapchat.png'}
                    height={30}
                    width={30}
                />
            );
        }
        else if ( network_id=== '3' )
        {
            return (
                <img
                    src={'/Icons/google.png'}
                    height={30}
                    width={30}
                />
            );
        }
        else if ( network_id=== '4' )
        {
            return (
                <AppleIcon/>
            );
        }
    };

    const classes = useStyles();
        return (
            <div className='material-ui'>
                <Autocomplete
                    className={classes.Select}
                    id="account_select"
                    options={clientAccountsData}
                    onChange={accountSelectedHandler}
                    getOptionLabel={option =>
                        {
                            return(
                                <Fragment>
                                    <Icon className={classes.icon}>
                                        {
                                        renderCorrectAccountChannelIcon(option.network_id)
                                        }
                                    </Icon>
                                    {option.accountName + ' (' + option.accountId + ')'}
                                </Fragment>
                            );
                        }
                    }
                    filterSelectedOptions
                    renderInput={params => (
                        <Fragment>
                            <TextField
                                {...params}
                                variant="outlined"
                                label="Select Account"
                                placeholder="Favorites"
                                margin="normal"
                                fullWidth
                            />
                        </Fragment>

                    )}
                />
            </div>
        );
};

SelectAccount.prototypes = {
    accountSelected: PropTypes.func.isRequired,
    clientAccountsData: PropTypes.array.isRequired,
};

const mapStateToProps = state => ({
    clientAccountsData: state.client.clientAccountsData,
});

export default connect(mapStateToProps, {})(SelectAccount);

EDIT!: Found a fix, we need to use renderOption to render the icon + text and use getOptionLabel just for the label text it looks like this:

<Autocomplete
                    className={classes.Select}
                    id="account_select"
                    options={clientAccountsData}
                    onChange={accountSelectedHandler}
                    getOptionLabel={option => option.accountName + ' (' + option.accountNumber + ')'}
                    renderOption={option => {
                        return (
                            <Fragment>
                                <Icon className={classes.icon}>
                                    {
                                        renderCorrectAccountChannelIcon(option.network_id)
                                    }
                                </Icon>
                                {option.accountName + ' (' + option.accountNumber + ')'}
                            </Fragment>
                        );
                    }}
                    filterSelectedOptions
                    renderInput={params => (
                        <Fragment>
                            <TextField
                                {...params}
                                variant="outlined"
                                label="Select Account"
                                placeholder="Favorites"
                                margin="normal"
                                fullWidth
                            />
                        </Fragment>

                    )}
                />

Upvotes: 12

Views: 16068

Answers (2)

KARTHIKEYAN.A
KARTHIKEYAN.A

Reputation: 20078

I have implemented the above case in the following way using renderOption property

<Autocomplete
    renderOption={React.useCallback((props, option, { inputValue }) => {
      return (
          <Box component='li' {...props}>
              <div style={{width: '20%'}}/><img src={'../src/img/Tables.svg'}/></div>{option.name}
          </Box>
      )
  })}
/>

Upvotes: 1

J&#250;lio Almeida
J&#250;lio Almeida

Reputation: 1869

I want to share maybe a new spin off of this solution that is based of the autocomplete example in the documentation (autocomplete demos). Keeps the image in the selected tag as well.

<Autocomplete
    multiple
    limitTags={2}
    id="multiple-limit-tags"
    options={top100Films}
    getOptionLabel={(option) => option.title}
    defaultValue={[top100Films[13], top100Films[12], top100Films[11]]}
    renderTags={options => 
    {
        return (
            options.map(option =>
                <Fragment>
                    <IconButton color="primary">
                        <img src={'../src/img/Tables.svg'}/> {/*Mock image, attribute in option*/}
                    </IconButton>
                        {option.title}
                </Fragment>))

    }}
    renderOption={option => {
        return (
            <Fragment>
                    <IconButton color="primary">
                        <img src={'../src/img/Tables.svg'}/> {/*Mock image, attribute in option*/}
                    </IconButton>
                {option.title}
            </Fragment>
        );
    }}
    renderInput={(params) => (
        <TextField 
            {...params}
            variant="outlined" 
            label="limitTags" 
            placeholder="Favorites" 
        />
    )}
  />

enter image description here

Upvotes: 8

Related Questions