Material UI - Select Menu with End Adornment

Viewed 17757

Is it possible to get an endAdornment into a Select menu in MaterialUI?

I want to add content to the right hand side of the down pointer on the select menu.

endAdornment={
   <InputAdornment position="end">
        <Insights />
   </InputAdornment>

<Select
   labelId="demo-mutiple-name-label"
   id="demo-mutiple-name"
   multiple
   value={fieldName}
   onChange={handleChange}
   input={<Input id="select-multiple-chip" />}
   renderValue={(selected) => (
     <div className={classes.chips}>
     {selected.map((value) => (
        <Chip key={value} label={value} className={classes.chip} />
        ))}
     </div>
     )}
     MenuProps={MenuProps}
   >
   {field.map((field) => (
    <MenuItem key={field} value={field} >
        {field}
    </MenuItem>
   ))}
                            
</Select>
6 Answers

I took Javier answer but did the styling a bit different. As he mentions, Material UI Select Component supports endAdornment, but, it doesn't work quite well with the Select arrow. The main problem is that whatever you put there, it will overlap it. Here's an example of how I did it.

First, define a class that you will apply to the InputAdornment element. You simply need to give it a bit of right padding so that it doesn't render on top of the arrow:

const useStyles = makeStyles((theme) =>
  createStyles({
    selectAdornment: {
      marginRight: theme.spacing(3),
    },
  })
);

Then just add the class to the InputAdornment in your Select

<FormControl className={classes.rowInputRoot} error={!!error}>
  <Select
    labelId="id"
    value={selectValue}
    endAdornment={
      <InputAdornment className={classes.selectAdornment} position="end">
        <CircularProgress size={20} />
      </InputAdornment>
    }
  >
    <MenuItem value="" selected>
      <em>Select</em>
    </MenuItem>
    {rowData.listValues?.map((value, i) => {
      return <MenuItem value={value[idPropName]}>{value.label}</MenuItem>;
    })}
  </Select>
</FormControl>;

This will render the adornment with a bit of margin right to avoid overlapping with the Select arrow.

Instead of using <Select>, we could use <TextField> with <MenuItem> in it.

<TextField
      style={{ width: "100%" }}
      name="cls"
      select
      label="Items"
      helperText="Please select Class"
      margin="normal"
      variant="outlined"
      InputProps={{
        endAdornment: (
          <InputAdornment position="start">something</InputAdornment>
        )
      }}
    >
      <MenuItem>Item 1</MenuItem>
      <MenuItem>Item 2</MenuItem>
      <MenuItem>Item 3</MenuItem>
    </TextField>
  );

See the sample sandbox example https://codesandbox.io/s/material-demo-forked-9vqb3?file=/demo.js

Current Material Ui Select Component supports endAdornment, but, it doesn't work quite well with the select arrow.

What I did was to add an startAdornment and added a makeStyles class to put the adornment in a absolute position, the makeStyle class has the following content:

const useStyles = makeStyles((theme) => ({
  selectAdornment: {
    "& .MuiButtonBase-root": {
      position: "absolute",
      padding: 0,
      right: "32px",
      top: "calc(50% - 12px)",
    },
  },
}));

Select look like this:

<Select
  {...props}
  onChange={handleChange}
  startAdornment={
    <InputAdornment position="start" className={classes.selectAdornment}>
      <IconButton>
        <Tooltip title="tooltip text">
          <HelpIcon
            color="primary"
          />
        </Tooltip>
      </IconButton>
    </InputAdornment>
  }
/>

Like other answers on this thread, the Material UI Select Component supports endAdornment and startAdornment but, like others have mentioned the select arrow will overlap with it.

My solution to this was actually overriding the position of the select arrow.

<Select
 labelId="id"
 value={selectValue}
 endAdornment={
  <IconButton>
    <Tooltip title="tooltip text">
      <HelpIcon
      color="primary"
     />
    </Tooltip>
  </IconButton>
}
/>

then, wherever you have your css, include:

.MuiSelect-icon { right: 40px !important; }

but it is entirely dependent on where you want your select arrow, so play around with the values depending on where you want the select arrow.

Will this work?

<FormControl>
    <Select {...props}>
        {values.map((value) => (
            <MenuItem
                key={value}
                value={value}
            >
                <Typography variant="inherit">{value}</Typography>
                <ListItemSecondaryAction>
                    <IconButton edge="end" aria-label="delete">
                        <Check />
                    </IconButton>
                </ListItemSecondaryAction>
            </MenuItem>
        ))}
    </Select>
</FormControl>

For anyone else trying to do this - I haven't figured out how to do it, but a work around that may be good enough is to put all the content that you want in the endAdornment in a right aligned FormHelper - so that it appears below the input box in the form field.

Related