style mui multiple autocomplete values in textField

Viewed 200

I want to create an autocomplete multiple but with a comma in selected values. When I choose multiple values, it makes bigger the component. But I want to make autocomplete just like select with multiple option. First image shows how autocomplete behaves in multiple selection. Second image, what I want when multiple selection occurs. my code:

<Autocomplete
                    disablePortal
                    id="serviceCities"
                    name="serviceCities"
                    value={formik.values.serviceCities}
                    onChange={(e, value) => formik.setFieldValue("serviceCities", value)}
                    options={cities}
                    loading={true}
                    loadingText="loading..."
                    multiple={true}
                    getOptionLabel={type => type.name}
                    sx={{ width: "100%", mt: "4%" }}
                    isOptionEqualToValue={(option, value) => option.id === value.id}
                    renderInput={(params) => <TextField {...params}
                        label="provide services in"
                        placeholder="type name of cities"
                        sx={{ ...styles.autoComplete, width: "100%" }}
                        InputLabelProps={{ shrink: true }}
                        error={formik.touched.serviceCities && Boolean(formik.errors.serviceCities)}
                        helperText={formik.touched.serviceCities && formik.errors.serviceCities}
                    />}
                />

how mui autocomplete multipla select shows:

the behavior I want:

thank you very much!

1 Answers

To display text instead of Chips, you can use the renderTags prop of <Autocomplete> to render <span> elements instead of <Chip> components. (Chip components are rendered by default when Autocomplete is used with the multiple prop.)

This jsFiddle demo has a demonstration. (Click "Run" to start the demo.) The code in the demo is compiled, but copied below. index.jsx was compiled to the file name index.js and located in the same directory as index.html.

The part of your question that says: When I choose multiple values, it makes bigger the component. might need more clarification. The Material-UI <Input> component automatically increases in height to accommodate selected options that are too long for the configured width. If you want to increase the width dynamically you could calculate a value for the width property of sx in the <Stack> component. This line in index.jsx would need to be updated:

<Stack spacing={3} sx={ { width: 500 } }>

There could be different approaches for calculating width based on the number of characters in the options, the number of options in each row of the <Input> component, etc.

index.html

<!DOCTYPE html>
<html>

    <head>
        <title>Material-UI Autocomplete Test</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>

    <body>
        <div id="testContainer" class="testContainer"></div>
        <script src="./index.js"></script>
        <noscript> Please enable javascript to view the site </noscript>
    </body>

</html>

index.jsx

// index.jsx

import * as React from 'react';
import ReactDOM from 'react-dom';
const container = document.getElementById( 'testContainer' );

import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import Stack from '@mui/material/Stack';


export default function ListItems() {

    /**
     * Select option items in the drop-down list.
     */
    const options = [
        { id: 0, value: 'Waldorf', someProperty: 'someValue' },
        { id: 1, value: 'Wright', someProperty: 'someValue' },
        { id: 2, value: 'Edlezold', someProperty: 'someValue' }
    ];

    /**
     * Items selected by the user for display in the input field.
     */
    const [ list, setList ] = React.useState( [] );

    function handleChange( event, inputs, reason ) {
        if ( 'selectOption' == reason ) {
            setList( inputs );
        } else if ( 'clear' == reason ) {
            setList( [] );
        }
    }

    return (
        <Stack spacing={3} sx={ { width: 500 } }>
            <Autocomplete
                multiple
                id="tags-filled"
                filterSelectedOptions={ true }
                fullWidth={ false }
                options={ options }
                getOptionLabel={ ( option ) => option.value }
                value={ list }
                isOptionEqualToValue={ ( option, value ) => option.value == value.value }
                renderInput={ ( params ) => {
                    return (
                        <TextField
                            { ...params }
                            variant="filled"
                            label="Autocomplete Test"
                            placeholder="Select item"
                            helperText="Select item from list"
                        />
                    );
                } }
                renderTags={ ( list ) => {
                    let displayList = list.map( ( item ) => item.value ).join( ', ' );
    
                    // Render <span> elements instead of <Chip> components.
                    return <span>{ displayList }</span>;
                } }
                onChange={ handleChange }
            />
        </Stack>
    );
}


/**
 * Inject component into DOM
 */
ReactDOM.render(
    <ListItems />,
    container
);

Related