Skip to content

autocompletes overlay position works wrong on mobile devices #6341

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

Closed
maku opened this issue Aug 8, 2017 · 59 comments · Fixed by #12119
Closed

autocompletes overlay position works wrong on mobile devices #6341

maku opened this issue Aug 8, 2017 · 59 comments · Fixed by #12119
Assignees
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@maku
Copy link

maku commented Aug 8, 2017

Bug, feature request, or proposal:

Bug

What is the expected behavior?

Correct overlay position so that the component can be used on mobile devices

What is the current behavior?

On mobile devices (e.g iphone6+ with latest IOS, Android etc.) the position of the overlay is strange.
Sometimes the overlay disappears or the overlay overlaps the input fields ...

So autocomplete is NOT usable on mobile devices....

What are the steps to reproduce?

E.g. use the https://material.angular.io/ demo for autocomplete on mobile devices

What is the use-case or motivation for changing an existing behavior?

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Angular 4.3.3, Material 2.0.0-beta.8

Is there anything else we should know?

@willshowell
Copy link
Contributor

The positioning of the autocomplete just changed to be more accurately connected to the input. Here is an example with the latest build: http://plnkr.co/edit/HnQwfr7WlNVLdP3P6ukQ?p=preview

However, I am still seeing some weird positioning in landscape mode with the keyboard open:

img_4975

@crisbeto
Copy link
Member

crisbeto commented Aug 8, 2017

The issue is that the keyboard animation throws off the positioning logic. I've been considering whether having a setTimeout on focus for iOS and Android would make sense @jelbourn?

@jelbourn
Copy link
Member

jelbourn commented Aug 8, 2017

@crisbeto that seems reasonable if we scope the delay to only apply for these cases. Let's address this after the overlay positioning refactor

@jelbourn jelbourn added the P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent label Aug 8, 2017
@maku
Copy link
Author

maku commented Aug 14, 2017

@crisbeto is there any timeframe until func is getting better on IOS -> Otherwise I have to consider to replace autocomplete temporarly...

@crisbeto
Copy link
Member

The initial plan was to address this after we refactor some of our positioning logic, but I suppose that shouldn't really change what we do in the autocomplete. There should be a way for you to patch it on your side temporarily, but it'll be very hacky, because it would need to access private properties on the autocomplete trigger.

@maku
Copy link
Author

maku commented Aug 14, 2017

@crisbeto what is the way to "patch" autocomplete so that it work better on IOS???

@crisbeto
Copy link
Member

I've been playing around with the approach I mentioned above, but it doesn't really work the way I expected it to. It seems like the autocomplete does figure out the proper position values, however iOS throws it off when it scrolls the input into the middle of the view. Delaying the positioning call doesn't help in this case.

@maku
Copy link
Author

maku commented Aug 16, 2017

@crisbeto Is there a solution to this problem? What is the recommended way to go?

@xiongemi
Copy link

Any update on this issue?

@mahmood-sajjadi
Copy link

@crisbeto, @maku is there any workaround or patch for this issue?

@crisbeto
Copy link
Member

crisbeto commented Aug 31, 2017

This is somewhat tricky to fix on our end, because iOS seems to shift the coordinate grid when it focuses the into view, which makes it so we can't recalculate the position correctly. The best approach for now might be to disable scrolling for the autocomplete altogether. See #5187 (comment).

@maku
Copy link
Author

maku commented Aug 31, 2017

@crisbeto dump question - how do other ui libraries handle this problem?

@crisbeto
Copy link
Member

crisbeto commented Aug 31, 2017

The easiest way to handle it would be to use position: absolute to position the panel, however that is problematic when dealing with focus and overflow.

@maku
Copy link
Author

maku commented Sep 2, 2017

@crisbeto I would really appreciate an advice what to do... - should we drop using autocomplete?? and looking for an alternative (also the fix #5187 does not work for me)
Is there anything in the pipeline? The component as it is is NOT usable on IOS.

Just to be curious - what problems does material2 have what other libs don't have (so that this stuff works on IOS)?

@maku
Copy link
Author

maku commented Sep 8, 2017

@crisbeto I really do not want to be annoying. But is there any kind of solution on the horizon?

@MatteoNY
Copy link

MatteoNY commented Oct 4, 2017

Any updates? using latest and issue with iOS positioning as well as touch. I can not select an item from autoComplete component. I'm using the code from your example to test. I have hammer js installed the toggle button works and requires hammer js as per your spec. Not sure why I can not select an item but positioning is still an issue. Thanks!

@LukasKlement
Copy link

LukasKlement commented Oct 4, 2017

This very issue is causing headaches on my side too.

The following two suggestions have helped the situation and make the autocomplete somewhat usable on iOS:

  1. Add cdkScrollable to your <main …> element (@crisbeto, #4557)
  2. Add custom scrolling strategy (@aitboudad, #5187)

@kasperhhk
Copy link

We have a related issue, maybe it's the same.

For us, the dropdown list gets hidden entirely by the keyboard, instead of the dropdown list going upwards (the autosuggest field is in the middle of the page).

https://imgur.com/a/nrBUw

@murilobd
Copy link

murilobd commented Nov 6, 2017

Any updates on this issue?! I'm facing the same problem!!

@michaeldev6
Copy link

michaeldev6 commented Nov 20, 2017

Just want to add my thoughts on this. As I am facing this issue as well. Not sure if any of this information will help, but figured to add some notes here.

When testing on an iPad in debug mode connected to a MacBook, I noticed that when highlighting the AutoCompletePanel in the HTML element in the debugger, it does highlight the element, and the highlight is shown directly underneath the input field. So the positioning of the css is correct.

But the kicker is that the browser is rendering the auto complete panel NOT where the highlighted HTML is. Which leads me to believe that it is something with how iOS Safari is rendering the HTML elements while the keyboard is up.

This is just a comment supporting @crisbeto comment regaring iOS shifting it's coordinate grid.

@stevenmcountryman
Copy link

For anyone still following this thread, hoping for a fix, I got tired of waiting for one and just scrapped the autocomplete from our project entirely and built my own component that looks identical but actually works, for all browsers and all platforms.

The idea is this:

HTML

<div>
    <mat-input-container class="//whatever class you have to make this the right width">
        <input #itemFilterInput matInput type="text" placeholder="ITEM" (click)="showItems = true">
    </mat-input-container>
    <mat-card [hidden]="!showItems" class="autocomplete">
        <mat-option *ngFor="let item of items" [value]="item.name" (click)="selectItem(item)">
            {{ item.name }}
        </mat-option>
    </mat-card>
</div>

TS

showItems: boolean = false;
@ViewChild('itemFilterInput') itemFilterInput: ElementRef;

ngOnInit() {
    Observable.fromEvent(this.itemFilterInput.nativeElement, 'keyup')
        .debounceTime(300)
        .distinctUntilChanged()
        .subscribe(() => {
            this.items = [];
            if (this.itemFilterInput.nativeElement.value && this.itemFilterInput.nativeElement.value.length > 1) 
            {
               this.itemService.getItemsBySearch(this.itemFilterInput.nativeElement.value).subscribe(items => {
               this.items = items;
               this.showItems = true;
            });
        }
    });
}

selectItem(item) {
    this.itemFilterInput.nativeElement.value = item.name;
    this.showItems = false;
}

CSS

.autocomplete {
    max-height: 150px; 
    overflow:auto; 
    position: fixed !important; 
    padding: 0 !important;
    z-index:1000;
}

@sava1192
Copy link

sava1192 commented Jan 5, 2018

Came to same approach as @stevenmcountryman. Created autocomplete by myself because MatAutocomplete is not usable on mobile at all.

@tomscript
Copy link

Friendly ping please. I'm using this on an email field so I can't create my own autocomplete.

@MikaStark
Copy link

I don’t want to use another dependency. My whole webapp is based on material. I can wait for a patch but i’m very surprised that kind of behavior tooks more than 9 months to be fixed.

@vovikdrg
Copy link

@MikaStark good for you in my case I didn't have choice. I must support mobile..

@MikaStark
Copy link

After 1 month, here is a little up 🙂

@waseemshaz
Copy link

https://www.w3schools.com/tags/tag_datalist.asp

Guys use HTML 5 Datalist, its working awesome

@stevenmcountryman
Copy link

@waseemshaz, looks like that isn't supported by Safari at all which makes it a no go

@joelcoxokc
Copy link

joelcoxokc commented May 6, 2018 via email

@MikaStark
Copy link

MikaStark commented Jun 6, 2018

June has come and no fix even after couple of material updates

@mhosman
Copy link

mhosman commented Jun 12, 2018

No news about this one?

@MikaStark
Copy link

Nope 😤 still P3 but no one cares 🤪

@sava1192
Copy link

sava1192 commented Jun 12, 2018

waitet for fix for so long, that switched to React already

@jpzwarte
Copy link
Contributor

See the explanation in #11946 where (i think) the problem is in the code (my issue is unrelated to mdAutocomplete, but also involves the iOS keyboard).

@jpzwarte
Copy link
Contributor

jpzwarte commented Jun 27, 2018

So aside from the PR, i also added a workaround to my custom component. The code below works for me on iOS: the overlay is positioned correctly when scrolling with the keyboard visible:

    this.overlayDir.positionChange.subscribe((position: ConnectedOverlayPositionChange) => {
      const clientRect = this.overlayDir.overlayRef.hostElement.getBoundingClientRect();

      if (clientRect.top !== 0) {
        const overlayElement = this.overlayDir.overlayRef.overlayElement,
              overlayY = position.connectionPair.overlayY;

        if (overlayY === 'top') {
          const top = parseInt(overlayElement.style.top);

          overlayElement.style.top = top + Math.abs(clientRect.top) + 'px';
        } else if (overlayY === 'bottom') {
          const bottom = parseInt(overlayElement.style.bottom);

          if (bottom >= Math.abs(clientRect.top)) {
            overlayElement.style.bottom = bottom + clientRect.top + 'px';
          }
        }
      }
    });

@jinder
Copy link

jinder commented Jun 27, 2018

@jpzwarte your workaround seems to work perfectly - thanks. My overlays now position correctly when the iOS keyboard is out.

@geoFlux
Copy link

geoFlux commented Jun 28, 2018

@jpzwarte I don't understand your solution. How does one get a reference to overlayDir? Do you have a more complete example?

@jinder
Copy link

jinder commented Jun 28, 2018

@geoFlux you can get it using a ViewChild on your cdkConnectedOverlay directive:

<ng-template #connectedOverlay="cdkConnectedOverlay" cdkConnectedOverlay></ng-template>

And then in your component:

  @ViewChild("connectedOverlay") private _connectedOverlay: CdkConnectedOverlay;

@vmachacek
Copy link

@jinder I was not able to make it work with sample provided. Do you mind sharing plunker, please?

@itsanmax
Copy link

itsanmax commented Jul 5, 2018

@stevenmcountryman : Thanks for your solution provided here: #6341 (comment). I've applied same solution in my project. This resolve issue of showing list options at correct position but getting issue with selecting option by clicking function "selectItem(item)". Issue here is, selectItem function fires on 2nd time click. It doesn't fire on first time click. Any idea how to solve this issue? It would be really great help if you can help to sort out this issue.

crisbeto added a commit to crisbeto/material2 that referenced this issue Jul 9, 2018
This is taking over from angular#11947. Fixes the connected overlay positioning being thrown off, if it is opened while an input is focused (e.g. when building an autocomplete component). The issue comes from the fact that the browser will offset the entire page in order to put the input in the middle and to make space for the virtual keyboard.

Fixes angular#6341.
@crisbeto crisbeto added the has pr label Jul 9, 2018
crisbeto added a commit to crisbeto/material2 that referenced this issue Jul 10, 2018
This is taking over from angular#11947. Fixes the connected overlay positioning being thrown off, if it is opened while an input is focused (e.g. when building an autocomplete component). The issue comes from the fact that the browser will offset the entire page in order to put the input in the middle and to make space for the virtual keyboard.

Fixes angular#6341.
jelbourn pushed a commit that referenced this issue Jul 11, 2018
This is taking over from #11947. Fixes the connected overlay positioning being thrown off, if it is opened while an input is focused (e.g. when building an autocomplete component). The issue comes from the fact that the browser will offset the entire page in order to put the input in the middle and to make space for the virtual keyboard.

Fixes #6341.
jelbourn pushed a commit that referenced this issue Jul 12, 2018
…12119)

This is taking over from #11947. Fixes the connected overlay positioning being thrown off, if it is opened while an input is focused (e.g. when building an autocomplete component). The issue comes from the fact that the browser will offset the entire page in order to put the input in the middle and to make space for the virtual keyboard.

Fixes #6341.
victoriaaa234 pushed a commit that referenced this issue Jul 25, 2018
…12119)

This is taking over from #11947. Fixes the connected overlay positioning being thrown off, if it is opened while an input is focused (e.g. when building an autocomplete component). The issue comes from the fact that the browser will offset the entire page in order to put the input in the middle and to make space for the virtual keyboard.

Fixes #6341.
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

Successfully merging a pull request may close this issue.