Mel
Mel

Reputation: 2715

Material UI - Select Menu with End Adornment

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>

Upvotes: 18

Views: 40435

Answers (8)

Habbu
Habbu

Reputation: 11

As everyone has said, Select doesn't support endAdornment very well. I found the best way around it to be using absolute positioning. This is very similar to javier's response, but it's important to set pointer events to "none", so that the adornment won't prevent the user from interacting with the dropdown arrow. Here is my solution with inline styles:

 <Select
    value={value}
    label="Label"
    endAdornment={
        <InputAdornment 
          position="end" 
          sx={{ pointerEvents: "none", position: "absolute", right: 35 }}>
            adornment
        </InputAdornment>
    }
  >
    <MenuItem value={1}>1</MenuItem>
    <MenuItem value={2}>2</MenuItem>
</Select>

If your elements overlap, adjust the width of the Select.

Upvotes: 1

Sumit Kumar Gupta
Sumit Kumar Gupta

Reputation: 71

Try this.

            <Select
                onChange={onChange}
                endAdornment={
                    xVisible ? (
                        <div
                            onClick={xClick}
                        >
                            <i className="bi bi-x-lg"></i>
                        </div>
                    ) : null
                }
                sx={{
                    "& .MuiSelect-iconOutlined": {
                        display: xVisible ? "none" : "",
                    },
                    "&.Mui-focused .MuiIconButton-root": {
                        color: "primary.main",
                    },
                }}
            >
                <MenuItem value="10">Ten</MenuItem>
                <MenuItem value="20">Twenty</MenuItem>
            </Select>

Upvotes: 0

jz1995
jz1995

Reputation: 11

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.

Upvotes: 1

Anil Sambasivan
Anil Sambasivan

Reputation: 149

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

Upvotes: 4

javier
javier

Reputation: 108

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>
      }
    />

Upvotes: 1

foreverAnIntern
foreverAnIntern

Reputation: 501

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>

Upvotes: 0

nachoargentina
nachoargentina

Reputation: 790

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.

Upvotes: 17

Mel
Mel

Reputation: 2715

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.

Upvotes: -3

Related Questions