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

Dropdown menu is misplaced when page scroll bar is not visible #1404

Closed
ahadjithoma opened this issue Oct 30, 2019 · 22 comments
Closed

Dropdown menu is misplaced when page scroll bar is not visible #1404

ahadjithoma opened this issue Oct 30, 2019 · 22 comments

Comments

@ahadjithoma
Copy link

Describe the bug
When the page has scroll bar, everything is fine. When the scroll bar is not visible, the dropdown menu is misplaced.

Screenshots

  • This is when the page do not have scroll bar

Annotation 2019-10-30 100237

  • And this is with scroll bar

Annotation 2019-10-30 100137

You can see the difference clearly.
I just upgrade to the latest version
I also tried

body {
  position: relative;
}

in styles

@varnastadeus varnastadeus added the needs reproduction needs reproducible example label Oct 30, 2019
@pjominet
Copy link

pjominet commented Oct 30, 2019

same issue here. What additional infos do you need, maybe I can provide them

@varnastadeus
Copy link
Member

a reproducible example would be best

@pjominet
Copy link

pjominet commented Oct 30, 2019

https://stackblitz.com/edit/angular-y51evj there :) hope that helps. Also for some reason the labels of the grouped items are white and therefore not visible, but they exist and you can click'em

@varnastadeus
Copy link
Member

solves your problem

body {
  position: relative;
}

@pjominet
Copy link

hmm strange, in the example I gave you this really fixes it, but in my own project I already had this specific body positioning, but it still breaks as if it were not there

@pjominet
Copy link

pjominet commented Oct 30, 2019

I just updated my stackblitz example, with

a) body position: relative
b) body min-height: 100vh, as I have to set this too in my project

this breaks it again, it is offset with no scrollbar and correct with scrollbar. So the problem comes from the combination of position: relative and min-height: 100vh

@ahadjithoma
Copy link
Author

thanks to @pjominet's last answer i discovered the root of our problem which is somehow similar.

In our project we are using a grid layout. To fix the problem i must set grid's height = 100%, but this is something that we should avoid due to our current layout

@ahadjithoma
Copy link
Author

any workarounds without having to set the body height to 100% ?

@kailynnelson
Copy link

We are looking for a similar solution in our own projects.

body { position: relative; } does not help.

@slavede
Copy link

slavede commented Feb 25, 2020

I've opened PR that fixes this. Hopefully, it gets in asap and new version is tagged.

@slavede
Copy link

slavede commented Feb 28, 2020

To hopefully push this PR more quickly here's explanation why does it happen. Scenario when you don't have scrollbar on your body. When ng-select generating dropdown, it sets class to it which appears under the body and then body gets scrollbar. Then positioning is calculated as if body would have scrollbar, but then after setting position vertically this scrollbar dissapears and positioning is now wrong since scrollbar got away (this PR will handle it in a way that it hides scrollbar always whenever it's calculating position)

@tncho
Copy link

tncho commented Mar 10, 2020

Any idea on when this PR is getting released / merged? Thanks

@slavede
Copy link

slavede commented Mar 10, 2020

It's pending review for more than 10 days now. I see @varnastadeus is assigned.

@slavede
Copy link

slavede commented Apr 6, 2020

Does anyone know any other maintainer of this project expect @varnastadeus. He keeps ignoring messages and PR.

@ahadjithoma
Copy link
Author

@slavede looks like @anjmao also maintains the project

@slavede
Copy link

slavede commented Apr 27, 2020

Here it is if you don't believe issue (it's forked example from official examples)

https://stackblitz.com/edit/angular-6c2svw?file=src%2Fbindings-default-example.component.ts

slavede added a commit to slavede/ng-select that referenced this issue Apr 27, 2020
DepickereSven pushed a commit to sofico-global/ng-select that referenced this issue May 28, 2020
@RubenVermeulen
Copy link

RubenVermeulen commented May 28, 2020

We're experiencing the same problem. Quite annoying. Would be great if a solution gets released.

Otherwise a great library ;)

@DepickereSven
Copy link

There is a bigger problem when you update the width of your screen.

Let say you have a list with on top a search bar to search. Next to that search bar, you have a dropdown to sort your list based on a property you can select from that dropdown.

image

The balk on the right represents the scrollbar.

But if you search in your search bar your list will be filtered so the scrollbar will disappear
image

So far no issue but when you open your dropdown you will see a mismatch in the UI

What is causing this mismatch? Well, this is all being calculated in the following function:

private _updatePosition() {
const select = this._select.getBoundingClientRect();
const parent = this._parent.getBoundingClientRect();
const offsetLeft = select.left - parent.left;
this._setOffset(parent, select);
this._dropdown.style.left = offsetLeft + 'px';
this._dropdown.style.width = select.width + 'px';
this._dropdown.style.minWidth = select.width + 'px';
}

The most important variable from this piece of code is this._select that variable is equal to the following variable:

this._select = this._dropdown.parentElement;

That one again is equal to the following variable:

this._dropdown = _elementRef.nativeElement;

So what is going wrong, well that variable will never update, is that an issue?
Yes because when you have a scrollbar he will calculate the difference from the left side and add that to the dropdown elements.

const select = this._select.getBoundingClientRect();
const parent = this._parent.getBoundingClientRect();
const offsetLeft = select.left - parent.left;

image

But when you have no scrollbar anymore because you filtered your list the variable that will calculate will not be updated. That is the issue because when the scrollbar disappears you will have more room on the left and that is causing the shift to the left.

image

@slavede
Copy link

slavede commented Jun 23, 2020

That's right, and my fix, fixes it. Well, here's PR #1601 (tests are failing, I'm under heavy fire on my regular job, so anyone can join the fix)

@DepickereSven
Copy link

@slavede I placed a comment but I can't push to your branch to fix the test.

But your PR doesn't solve the issue that this._dropdown.parentElement; doesn't update

@david-ding
Copy link
Contributor

david-ding commented Jul 26, 2020

Looks like the issue is when we appending the dropdown menu to another container, we are waiting for the dom element to be inserted before calculating the left offset. Problem with this is after appending the menu, it could have triggered the scrollbar to appear, and our left offset is calculated based on when scrollbar is shown. And after we re-positioned the menu, the scrollbar disappears and we end up with misaligned menu.

I've tried another approach (PR #1695) - basically I separated updates to the X and Y offset, so that we calculate the left offset before appending the menu, and calculate the vertical offset after appending as usual, which seems to fix the issue.

I've also added event listener so it can react to window resize too.

Alban34 pushed a commit to Alban34/ng-select that referenced this issue Jan 7, 2021
Fix defect ng-select#1404 on branch 3.x by backporting merge ng-select#1739
@gauravmasand09
Copy link

gauravmasand09 commented Mar 7, 2021

Hi Everyone , was able to fix the issue by using min-height:100vh in my root div,
e.g -

<div class="container-fluid" style="min-height: 100vh;">
  <ng-container *ngIf="formLoaded; else loading">
    <div class="row">
      <div class="col-md-12">
        <ngb-accordion>
            <ngb-panel>
               ** here i am using form tag inside of form tag i am using ng-select **
            </ngb-panel>
        </ngb-according>
      </div>
    </div>
 </ng-container>
</div>

As u can see for my div 'container-fluid' from here my whole page starts so for this whole page i have given a min-height of 100vh this is what is rendered in my router-outlet so if u guys wanna use this in your root component tag u can use this property and it will work. Its working fine for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants