ngx-bootstrap: Modal keeps body class `modal-open` on after closing, causing scrollbars to disappear
Description
When you open and close modals, the <body> tag still has the CSS class modal-open.
This has the unfortunate effect of disabling scrolling in the page, because of the style
body.modal-open {overflow: hidden; }, which is correct when the modal is open, just not when it’s closed.
How to reproduce
Generate an Angular CLI application, and add ngx-bootstrap 1.7.1.
Add a modal popup, show it and hide it, and inspect the <body> tag in browser devtools.
Notes
As mentioned in https://github.com/valor-software/ngx-bootstrap/pull/1987#issuecomment-311391785, I think this was introduced as part of implementing the nested modals support. It seems that when the modal is animated, which is the default, something happens and the component thinks it’s nested, and does not clear the modal-open CSS class.
A possible workaround is to disable animations, which can be done globally by adding a directive like:
import { Directive } from '@angular/core';
import { ModalDirective } from 'ngx-bootstrap/modal/modal.component';
@Directive({
// tslint:disable-next-line:directive-selector
selector: '[bsModal]',
exportAs: 'bs-modal-override'
})
export class BsModalOverrideDirective {
constructor(private modal: ModalDirective) {
modal.isAnimated = false;
}
}
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 4
- Comments: 33 (6 by maintainers)
i still can see the issue in 1.8.1
Closing, until we have something reproducible 😃
Still have this issue using ngx-bootstrap using 6.2.0
My use case is slightly different than what is described above, but symptom is the same. The body tag is incorrectly marked with “model-open” class, when no modal is open.
My use case is:
After tracing through the ngx-bootstrap-modal.js, I discovered that even though the 2nd modal dialog is NOT nested, ngx-bootstrap thinks it is because in the “show()” method, the “modal-open” class is still attached to the body element as a result of the opening of the 1st modal dialog. And when that 2nd modal is closed, because it has been marked as isNested = true, the “hideModal()” method does not remove the “modal-open” class or call resetScrollbar(). Now you are stuck, because both modal dialogs are closed, but the class is still applied.
I think the root of the issue is that the existence of the class “modal-open” is essentially the arbiter of whether or not a modal is considered to be nested. Problem is, that class only gets removed as part of the hideModal() method. And that method gets executed inside of the hide() method on a 300 ms delay, if config.animated == true (which it is by default). And the execution of hideModal() actually gets cancelled by the show() method call of the 2nd modal.
So the upshot is, if you call show() on a modal dialog within 300 ms of calling hide() on a modal dialog. You willl end up with this problem.
I can workaround this by setting config.animated = false, because it effectively gets rid of that 300 ms delay.
This issue is still present in 6.1.0. At this point I’m going to have to stop using this package. It’s become unbearable for my users.
I’m using version 5.1.2 and am also experiencing this issue. Updated to 5.5.0 and the issue still occurs.
Solution
Was with this problem. It turned out that I imported the module twice, which contained imports to the ModalModule.
Make sure the ModalModule is only imported once on all project.
Everyone sees this issue, and we all agree that the timeout is causing the nested logic to get tripped up and mark dialogs nested when they aren’t. I’m going to repost this solution I outlined years ago:
at version 5.1.1 we still have this issue.
this loader is being dynamically. we resulted to a work around which is being recommended.
document.body.classList.remove('modal-open')my solution was to use
BsModalServiceto load only one modal template at a time and to gain more control over events and triggers.On Tue, Oct 3, 2017 at 3:19 PM, Henry Ollarves notifications@github.com wrote:
fixed in v1.8