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] Adding items to options causes scroll to go to the top of the list (paging) #30249

Closed
2 tasks done
LuigiMaestrelli opened this issue Dec 17, 2021 · 30 comments
Closed
2 tasks done
Labels
bug 🐛 Something doesn't work component: autocomplete This is the name of the generic UI component, not the React module! duplicate This issue or pull request already exists regression A bug, but worse

Comments

@LuigiMaestrelli
Copy link

LuigiMaestrelli commented Dec 17, 2021

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

I'm implementing async load with pagination with the Autocomplete.
When the listbox is open and the user scroll to the bottom, we load the next page and add the new options.
After adding, the position of the scroll on the listbox is reseted and the scroll goes to the top.

Expected behavior 🤔

The scroll position should not change so the user can continue the search for the option

Steps to reproduce 🕹

I've used the Select Country example in the docs and tweek to load the countries with paging.
I was abe to reproduce the issue without any async request, just loading more items from the fixed array.

https://codesandbox.io/s/confident-kare-5n6i6

Context 🔦

No response

Your environment 🌎

@emotion/react: 11.7.1
@emotion/styled: 11.6.0
@mui/material: 5.2.4
react: 17.0.2

`npx @mui/envinfo`

System:
OS: Windows 10 10.0.19044
Binaries:
Node: 16.12.0 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.17 - C:\Program Files\nodejs\yarn.CMD
npm: 8.3.0 - C:\Program Files\nodejs\npm.CMD
Browsers:
Chrome: Not Found
Edge: Spartan (44.19041.1266.0), Chromium (96.0.1054.57)

@LuigiMaestrelli LuigiMaestrelli added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Dec 17, 2021
@marr
Copy link

marr commented Dec 20, 2021

I've been trying to get help with this same issue but have received: no response on one ticket, and closure of another ticket with no explanation.

This CSB also illustrates the issue: https://codesandbox.io/s/autocomplete-scroll-bug-39wfv?file=/src/App.js

@LuigiMaestrelli
Copy link
Author

Don't now if helps, but I have an older project running some v4 version and this kind of use was working.
At the time the Autocomplete component was still in the lab package

@andrejunges
Copy link
Contributor

Indeed this issue didn't exist on v4.

Looks like the problem is this logic https://github.com/mui-org/material-ui/blob/3735493e98b0f15390642f4b134eff0212c652a6/packages/mui-base/src/AutocompleteUnstyled/useAutocomplete.js#L341 when there's no selected item.

@siriwatknp siriwatknp added bug 🐛 Something doesn't work component: autocomplete This is the name of the generic UI component, not the React module! good first issue Great for first contributions. Enable to learn the contribution process. regression A bug, but worse and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer bug 🐛 Something doesn't work labels Jan 7, 2022
@ShivamTyagi12345
Copy link

i would like to help
/assign

@oliviertassinari oliviertassinari added the bug 🐛 Something doesn't work label Jan 8, 2022
@glaucoheitor
Copy link
Contributor

Hey @ShivamTyagi12345, are you still working on this issue? I am currently facing the exact same problem and would like to work on it if needed. Thanks!

@ShivamTyagi12345
Copy link

Hey @ShivamTyagi12345, are you still working on this issue? I am currently facing the exact same problem and would like to work on it if needed. Thanks!

yes @glaucoheitor thanks for checking in.yes! I am working on my PR

@abhishekdubey1
Copy link

@ShivamTyagi12345 if you need help, I would also like to help with this. Thanks.

@ShivamTyagi12345
Copy link

@ShivamTyagi12345 if you need help, I would also like to help with this. Thanks.

Sure , if u have done any commits ,I would be happy to look and collaborate

@kshitij-p
Copy link

@ShivamTyagi12345 Hey how is your PR going ? I am working on this issue as well right now as well. Would love to help and collaborate. For anyone else also looking into this - https://github.com/mui-org/material-ui/blob/3735493e98b0f15390642f4b134eff0212c652a6/packages/mui-base/src/AutocompleteUnstyled/useAutocomplete.js#L373

The above line seems to be responsible for scrolling the list to the top and temporarily commenting it out seems to stop this happening. I don't know why this is happening however, but I am looking into it rn.

@ShivamTyagi12345
Copy link

/unassign

@ajlamarc
Copy link

Need a contribution for school, I will also look into this issue

@kshitij-p
Copy link

Opened a PR #30719 proposing a fix. Please read the PR message provided with it which includes a question I have regarding the demos/docs part of the PR.

@aakash-lohono
Copy link

aakash-lohono commented Jan 31, 2022

Hi,
as an intermediate solution

observe role="list-box", useAutocomplete expects it to be role="listbox"

import React, { ForwardedRef, forwardRef, useImperativeHandle, useRef } from "react";

interface ListBoxProps extends React.HTMLAttributes<HTMLUListElement> {
}

const ListBox = forwardRef(
  function ListBoxBase (
    props: ListBoxProps,
    ref: ForwardedRef<HTMLUListElement>,
  ) {
    const { children, ...rest } = props;

    const innerRef = useRef<HTMLUListElement>(null);

    useImperativeHandle<NullableUlElement, NullableUlElement>(ref, () => innerRef.current);

    return (
      <ul
        {...rest}
        ref={innerRef}
        role="list-box"
      >
        {children}
      </ul>
    );
  },
);

export default ListBox;

type NullableUlElement = HTMLUListElement | null;
import React from "react";
import { Autocomplete } from "@mui/material";
import ListBox from "./ListBox";

function HelloWorld () {
  return (
    <Autocomplete 
      {...someProps}
      ListboxComponent={ListBox}
    />
  );
}

this will also do away with hover and selection styles, to fix that, add the following somewhere globally

.MuiAutocomplete-popper .MuiAutocomplete-option[aria-selected='true'] {
  background: dodgerblue; // change accordingly
  color: white; // change accordingly
}

.MuiAutocomplete-popper .MuiAutocomplete-option[role='option'][aria-selected='false']:hover {
  background: rgba(0, 0, 0, 0.1); // change accordingly
}

@alveloper

This comment was marked as off-topic.

@tugay-radity
Copy link

Hello, we have the same issue, when will this get fixed?

@sirartemis
Copy link
Contributor

Hi , everybody!
@LuigiMaestrelli , until the bug is fixed, you can try my solution. I hope it gives a result similar to what you expected

https://codesandbox.io/s/clever-noether-5b93i2?file=/Autocomplete.js

@LuigiMaestrelli
Copy link
Author

Hi , everybody! @LuigiMaestrelli , until the bug is fixed, you can try my solution. I hope it gives a result similar to what you expected

https://codesandbox.io/s/clever-noether-5b93i2?file=/Autocomplete.js

It seems to have se same problem, the scroll resets when a new page is loaded.
For now, I'm using the solution from @aakash-lohono

@devcydo
Copy link

devcydo commented May 24, 2022

Hi! I would like to contribute, anyone working on this?

@siriwatknp siriwatknp mentioned this issue May 25, 2022
2 tasks
@ysheep-js
Copy link

Hi , everybody! @LuigiMaestrelli , until the bug is fixed, you can try my solution. I hope it gives a result similar to what you expected
https://codesandbox.io/s/clever-noether-5b93i2?file=/Autocomplete.js

It seems to have se same problem, the scroll resets when a new page is loaded. For now, I'm using the solution from @aakash-lohono

You need to copy ./Autocompletes.js to ./src/Autocompletes.js, then it works.

@mnajdova
Copy link
Member

mnajdova commented Jun 8, 2022

I've closed the ongoing PR on this issue, there wasn't any activity for some time. For anyone coming on the issue and want to try a fix, #30719 (comment) could be a good start.

@skypyxis
Copy link

Hi , everybody! @LuigiMaestrelli , until the bug is fixed, you can try my solution. I hope it gives a result similar to what you expected
https://codesandbox.io/s/clever-noether-5b93i2?file=/Autocomplete.js

It seems to have se same problem, the scroll resets when a new page is loaded. For now, I'm using the solution from @aakash-lohono

You need to copy ./Autocompletes.js to ./src/Autocompletes.js, then it works.

This works (storing scroll position and setting it after new data is loaded and appended) but it has one problem:
If we scroll the results in the list with the keyboard (down arrow key) when new data is appended the focused item goes back to the first item in the list.
Any idea how can we solve this?

@oliviertassinari oliviertassinari removed the good first issue Great for first contributions. Enable to learn the contribution process. label Jul 25, 2022
@MatetlotDev
Copy link

MatetlotDev commented Sep 23, 2022

Hi, I had the same issue for creating a paginated Autocomplete Dropdown with Material-ui. Every time the component refresh the list goes back to the top. The problem is that when we add some options to the list two props get updated and re-render the component. So here's what I did for a workaround :

`
import React, { useState, useEffect, useRef } from 'react';

const [position, setPosition] = useState(0);
const listElem = useRef();
const mounted = useRef();

useEffect(() => {
    if (!mounted.current) mounted.current = true;
    else if (position && listElem.current) 
         listElem.current.scrollTop = position - listElem.current.offsetHeight;
  })

// Autocomplete
          ListboxProps={{
          ref: listElem,
          onScroll: ({ currentTarget }) => {
            const scrollPosition =
              currentTarget.scrollTop + currentTarget.clientHeight;
              
            if (currentTarget.scrollHeight - scrollPosition <= 1 && nextPage) {
              setPosition(scrollPosition);
              loadMore.current.style.display = 'block';
              onInputValueChange(null, nextPage);
            }
          },
        }}

`

Hope it helps !

@MostafaKMilly
Copy link

Thanks @aakash-lohono the problem was solved
Actually, to solve this problem we just need to pass role: "list-box" as to ListboxProps

@Saul-Garcia
Copy link

Saul-Garcia commented Oct 4, 2022

Thanks @aakash-lohono the problem was solved Actually, to solve this problem we just need to pass role: "list-box" as to ListboxProps

@MostafaKMilly by changing the role to "list-box", can you still access to the list elements with the keyboard?. I tried but breaks accesibility for me.

@MostafaKMilly
Copy link

@Saul-Garcia Yes it breaks accessing options elements using keyboard :)

@michaldudak
Copy link
Member

There is another open issue describing this problem: #29508. I'm closing this one and let's continue the discussion in the original issue.

@michaldudak michaldudak closed this as not planned Won't fix, can't repro, duplicate, stale Oct 28, 2022
@michaldudak michaldudak added the duplicate This issue or pull request already exists label Oct 28, 2022
@devandrews
Copy link

Thanks @aakash-lohono the problem was solved Actually, to solve this problem we just need to pass role: "list-box" as to ListboxProps

For the ones with persisting errors, this solution works when you are not using a custom ListboxComponent. As mine was not necessary it solves the issue.

@JakubKontra
Copy link

Hello guys, thanks for your advices. When will it be merged? :)

@dbehmoaras
Copy link

If anyone is still having issues with this, try this approach:

To solve this in our codebase, I followed the approach in the youtube link below instead, using the MUI text field for the input and the MUI popper for the dropdown feature, effectively rebuilding the Autocomplete using two separate components. In our case, I used the IntersectionObserver to fire fetchMore query when reaching the bottom element (customizable to your desire of course) and used the ResizeObserver to make it responsive to viewport size. With this approach, it helps to think of infinite scroll as a paginated query, increasing the offset every time you reach the bottom of the list. You could get fancy as well by adding a loader each time the fetchMore query fires.
https://www.youtube.com/watch?v=NZKUirTtxcg

Full credit goes to Web Dev Simplified for sharing this approach. (Before anyone asks, no I am not Web Dev Simplified nor am I involved with the channel or its members in anyway).

@adi518
Copy link

adi518 commented May 18, 2024

@MostafaKMilly It's not considered a fix if it breaks something, which is accessibility in this case. Anyway, this was fixed for v5, but not everyone can just jump to the next major version. See #35735.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: autocomplete This is the name of the generic UI component, not the React module! duplicate This issue or pull request already exists regression A bug, but worse
Projects
None yet
Development

Successfully merging a pull request may close this issue.