Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AutoComplete] How to add scroll bar inside the render tags #20782

Closed
2 tasks done
hadasmaimon opened this issue Apr 26, 2020 · 14 comments
Closed
2 tasks done

[AutoComplete] How to add scroll bar inside the render tags #20782

hadasmaimon opened this issue Apr 26, 2020 · 14 comments
Labels
component: autocomplete This is the name of the generic UI component, not the React module! support: Stack Overflow Please ask the community on Stack Overflow

Comments

@hadasmaimon
Copy link

hadasmaimon commented Apr 26, 2020

  • The issue is present in the latest release.
  • I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 😯

How to add scroll bar inside the autocomplet to avoid too many lines as here:

image
That question was posted in stack-overflow but had no answers
https://stackoverflow.com/questions/59917803/how-to-reduce-the-height-of-autocomplete-component-of-material-ui

(when I added maxWidth and overflow auto it broke the limit tag
and broke the location of the search icon

image
)

Expected Behavior 🤔

Add scrolling option
image

@oliviertassinari oliviertassinari added the support: Stack Overflow Please ask the community on Stack Overflow label Apr 26, 2020
@support
Copy link

support bot commented Apr 26, 2020

👋 Thanks for using Material-UI!

We use GitHub issues exclusively as a bug and feature requests tracker, however,
this issue appears to be a support request.

For support, please check out https://material-ui.com/getting-started/support/. Thanks!

If you have a question on StackOverflow, you are welcome to link to it here, it might help others.
If your issue is subsequently confirmed as a bug, and the report follows the issue template, it can be reopened.

@support support bot closed this as completed Apr 26, 2020
@oliviertassinari oliviertassinari added the component: autocomplete This is the name of the generic UI component, not the React module! label Apr 26, 2020
@oliviertassinari
Copy link
Member

oliviertassinari commented Apr 26, 2020

The Gmail UX,

Capture d’écran 2020-04-26 à 21 57 38

You probably want to rethink your approach of the problem, in any case, we don't have the bandwidth to provide consulting on it here

@hadasmaimon
Copy link
Author

I tried it in Gmail,
And once I added more than a certain number of emails,
It added a scroll...
So maybe there is an idea for an existing solution,please?
image

@hadasmaimon
Copy link
Author

@oliviertassinari the problem was:
when wrapping renderTags content with div, this causes startAdornment.length to equal 1 instead of number of tags (because the tags are contained within the parent div)
As a result, the limit tag does not appear, since more is not >0 (the result is negative)

My solution was:
Wrap the tags only on OnOpen

Autocomplete code:

if (limitTags > -1 && Array.isArray(startAdornment)) {
    const more = startAdornment.length - limitTags;
    if (limitTags && !focused && more > 0) {
      startAdornment = startAdornment.splice(0, limitTags);
      startAdornment.push(
        <span className={classes.tag} key={startAdornment.length}>
          {getLimitTagsText(more)}
        </span>,
      );
    }
  }

@hadasmaimon
Copy link
Author

related to: #19137

@sfaman
Copy link

sfaman commented Jun 22, 2021

use condition on the renderTags to make it scrollable onFocus. Here is an Example
renderTags={(value, getTagProps) => {
if (this.state.showOwnersScroll) {
return (
<div className="d-flex" style={{overflow: 'auto'}}>
{value.map((option, index) => (
<Chip
color="primary"
deleteIcon={}
label={
option.title.length > 10
? option.title.substring(0, 7) +
"..."
: option.title
}
size="small"
{...getTagProps({ index })}
/>
))}

);
} else {
return value.map((option, index) => (
<Chip
color="primary"
deleteIcon={}
label={
option.title.length > 10
? option.title.substring(0, 7) + "..."
: option.title
}
size="small"
{...getTagProps({ index })}
/>
));
}
}}
onFocus={() =>
this.setState({ showOwnersScroll: true })
}
onBlur={() =>
this.setState({ showOwnersScroll: false })
}

@Nishant-Pall
Copy link

Has this issue been resolved? I've been facing the same problem but can't seem to find a viable solution

@Nishant-Pall
Copy link

@oliviertassinari the problem was: when wrapping renderTags content with div, this causes startAdornment.length to equal 1 instead of number of tags (because the tags are contained within the parent div) As a result, the limit tag does not appear, since more is not >0 (the result is negative)

My solution was: Wrap the tags only on OnOpen

Autocomplete code:

if (limitTags > -1 && Array.isArray(startAdornment)) {
    const more = startAdornment.length - limitTags;
    if (limitTags && !focused && more > 0) {
      startAdornment = startAdornment.splice(0, limitTags);
      startAdornment.push(
        <span className={classes.tag} key={startAdornment.length}>
          {getLimitTagsText(more)}
        </span>,
      );
    }
  }

Can you please send over the complete code for the AutoComplete component that you implemented?

@martin-trajanovski
Copy link

martin-trajanovski commented Nov 26, 2021

Has this issue been resolved? I've been facing the same problem but can't seem to find a viable solution

@Nishant-Pall you probably need something like this if you want to limit the tags all the time not only when it's not focused because in the official documentation there is an example with limitTags property but it's not limiting the tags when input is focused.. I am limiting the tags to 1 in my example but you can adjust to your needs.

   renderTags={(value, getTagProps) => {
        const numTags = value.length;
        const limitTags = 1;

        return (
          <>
            {value.slice(0, limitTags).map((option, index) => (
              <Chip
                {...getTagProps({ index })}
                key={index}
                label={option.name}
              />
            ))}

            {numTags > limitTags && ` +${numTags - limitTags}`}
          </>
        );
      }}

@rakeshptech9
Copy link

rakeshptech9 commented Aug 8, 2023

Here is how we got it working.
didn't need to add any conditional toggle, this automatically handled scroll behaviour on selected options when in focus mode and the limit tags behaviour when no in focus.

style: { height: 'auto', maxHeight: '500px', overflow: 'auto' },

renderInput={(params) => (
          <>
            <TextField
              {...params}
              sx={{ ...styles.textField }}
              placeholder={params.InputProps.startAdornment ? undefined : 'Select ***/s'}
              InputProps={{
                ...params.InputProps,
                disableUnderline: true,
                **_style: { height: 'auto', maxHeight: '500px', overflow: 'auto' },_**
                startAdornment: (
                  <>
                    <InputAdornment position="start">
                      <CustomIcon pathfill={palette.customBlue.primaryBlue} sx={{ ...svgStyles.icon }} />
                    </InputAdornment>
                    {params.InputProps.startAdornment}
                  </>
                ),
              }}
            />
          </>
        )}

@Miguel-A-Jara
Copy link

This worked for me:

<Autocomplete
  renderTags={(values, getTagProps) => (
    <Box sx={{ maxHeight: theme => theme.spacing(8), overflowY: 'auto' }}>
      {values.map((value, index) => (
        <Chip
          {...getTagProps({ index })}
          key={index}
          label={renderOption(value)}
        />
      ))}
    </Box>
  )}
/>

Basically just add a <Box /> that wraps your list of items. This box should have a maxHeight & overflowY set to auto.

Note that my maxHeight is a value I calculate from my theme. You can add any value you think fits well your project.

@Kilowhisky
Copy link

@Miguel-A-Jara

Based on the source code here:

if (renderTags) {
startAdornment = renderTags(value, getCustomizedTagProps, ownerState);
} else {
startAdornment = value.map((option, index) => (
<Chip
label={getOptionLabel(option)}
size={size}
{...getCustomizedTagProps({ index })}
{...ChipProps}
/>
));
}

Made a very slight change to your code above and it works great!

    renderTags={(values, getTagProps, owner) => (
      <Box sx={{ maxHeight: "300px", overflowY: 'auto' }}>
        {values.map((value, index) => (
          <Chip
            label={owner.getOptionLabel(value)}
            size={owner.size}
            {...getTagProps({ index })}
            {...owner.ChipProps}
          />
        ))}
      </Box>
    )}

I also had to add some logic to stop the popup Icon from appearing or else the scroll box appeared next to the popup icon in a weird way.

@okrahul
Copy link

okrahul commented Jun 26, 2024

I am facing the same issue with the Autocomplete component when using it in multiple mode. When the number of selected chips exceeds the maximum height, the chips are not displayed correctly, and the component does not become scrollable as expected.

I have tried implementing the solutions mentioned in previous issues, including setting the ListboxProps with a maxHeight and adjusting the PaperComponent height, but none of these solutions have resolved the issue.

if any one have solution pls let me know

@okrahul
Copy link

okrahul commented Jun 26, 2024

<Autocomplete
multiple
fullWidth
options={Data}
value={values.data}
getOptionLabel={(opt) => ${opt.name}}
isOptionEqualToValue={(opt, val) => opt.id === val.id}
renderOption={(props, opt, { selected }) => (
<li {...props}>
<Checkbox
checked={selected}
style={{ marginRight: 8 }}
size="small"
/>
{name}

)}
renderInput={(params) => (
<TextField
label='name'
{...params}
/>
)}
disableCloseOnSelect
sx={{
maxHeight: 120, // this property i applied
overflowY: "scroll", // this property i applied
py: 0.5,
...commonStyle,
"& .MuiOutlinedInput-notchedOutline": {
borderRadius: 2,
},
"& .MuiChip-root": {
backgroundColor: "rgba(56, 125, 255, 0.16)",
color: "#004EDE",
fontSize: "14px",
fontWeight: 600,
},
"& .MuiChip-root .MuiChip-deleteIcon": {
color: "#004EDE",
},
"&.MuiInputBase-root": {
fontSize: "14px",
fontWeight: 700,
},
}}
noOptionsText={No option}
PaperComponent={(paperProps) => {
const { children, ...restPaperProps } = paperProps;
return (
<Paper
{...restPaperProps}
sx={{ maxHeight: "190px", overflowY: "auto" }}
>
<Box onMouseDown={(e) => e.preventDefault()} pl={1.5} py={0.5}>
<FormControlLabel
onClick={(e) => {
e.preventDefault();
setSelectAll((prev) => {
if (!prev) {
void setFieldValue("designationMapping", designationData);
} else {
void setFieldValue("designationMapping", []);
}
return !prev;
});
}}
label={
<Typography variant="body3" sx={{ fontWeight: 600 }}>
Select all

}
control={

}
/>


{children}

);
}}
/>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: autocomplete This is the name of the generic UI component, not the React module! support: Stack Overflow Please ask the community on Stack Overflow
Projects
None yet
Development

No branches or pull requests

9 participants