-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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
bug(Datepicker): Calendar's position is being switched to upside even when there's no space to fit it #6965
Comments
Any news about this? One user complained today (I told him to press F11 to change the browser to full screen mode). Maybe I use the touch UI mode for now or other users can be confused. cc @mmalerba |
I believe it tries to position the calendar below and if there's not enough room it tries to position it above. If there's still not enough room it chooses whichever had more space available (in this case above). But I agree that it doesn't work so well here... I believe @jelbourn is working on a new positioning strategy that pushes the content back on screen. Is that ready yet Jeremy? |
It's still in-progress, should be soon-ish See #6534 |
Hi, @mmalerba and @jelbourn, I realized that #9153 was merged in March but, this undesired behavior is still there. The datepicker calendar, IMO, should be shifted down when there's no room above to show the header. It's better to hide part of the body at the bottom than hide the header (as, theoretically, you could scroll down to get to the bottom). And here I see an additional problem: even if you have the possibility to scroll up the page while the calendar is opened to try to make the calendar header visible, the scrolling is locked. Wouldn't it be better to release the scrolling while the calendar is opened? In fact, I should be able to tell the overlay to consider a page offset from top/bottom. Look at the image below: shouldn't I be able to tell the position strategy to not cover the top navbar, by considering the page available space to start below the navbar (somehow telling the position strategy to offset from top/bottom by an amount of pixels)? |
can you please let me know the progress on this issue? Looks like the pull request is in progress for the last 50 days.. |
@blackblood19, as a workaround you can switch your datepickers to touchUi when it's necessary. I'm using this directive to accomplish this task automatically (if you change the viewport size while the calendar is opened it becomes a little messy, and it's back to normal if you close and open the calendar again => currently I can live with that since most of the time the viewport size is defined only when the browser is opened for the first time): <mat-datepicker appAutoModeSwitch></mat-datepicker> @Directive({
selector: '[appAutoModeSwitch]',
})
export class AppDatepickerSwitchDirective implements OnInit, OnDestroy {
_isShortScreen = false;
private _monitorScreenHeight$ = fromEvent(window, 'resize');
private _destroy$ = new Subject<void>();
constructor(
private _zone: NgZone,
@Self()
@Host()
private datepicker: MatDatepicker<any>,
) {
this._zone.runOutsideAngular(() => {
this._monitorScreenHeight$.pipe(takeUntil(this._destroy$)).subscribe(() => {
this._switchDatepickerMode();
});
});
}
ngOnInit() {
setTimeout(() => (this.datepicker.touchUi = this._isThereFreeSpace()));
}
ngOnDestroy() {
if (!!this._destroy$ && !this._destroy$.closed) {
this._destroy$.next();
this._destroy$.complete();
}
}
/** returns true if the amount of free space is not enough to show the datepicker*/
private _checkWhetherSpaceIsCritical(): boolean {
const windowHeight = this._getWindowHeight();
const inputElementRect = this.datepicker._datepickerInput
.getPopupConnectionElementRef()
.nativeElement.getBoundingClientRect();
const inputHeight = inputElementRect.height;
const freeTopSpace = inputElementRect.top;
const freeBottomSpace = windowHeight - (freeTopSpace + inputHeight);
return freeTopSpace < 354 && freeBottomSpace < 354;
}
private _switchDatepickerMode() {
const notEnoughFreeSpace = this._checkWhetherSpaceIsCritical();
if (notEnoughFreeSpace !== this.datepicker.touchUi) {
this._zone.run(() => (this.datepicker.touchUi = notEnoughFreeSpace));
}
}
private _getWindowHeight() {
return window.innerHeight
? window.innerHeight
: document.documentElement.clientHeight || document.body.clientHeight || 0;
}
} |
I'm sorry, but I think I am not the right guy... You must have confused or
have a typo in the contact.
Il sab 21 lug 2018, 21:22 Juliano <[email protected]> ha scritto:
… @blackblood19 <https://github.com/blackblood19>, as a workaround you can
switch your datepickers to touchUi when it necessary. I'm using this
directive to accomplish this task:
<mat-datepicker appDatepickerSwitch></mat-datepicker>
@directive({
selector: '[appDatepickerSwitch]',
})export class AppDatepickerSwitchDirective implements OnInit, OnDestroy {
_isShortScreen = false;
private _monitorScreenHeight$ = fromEvent(window, 'resize');
private _destroy$ = new Subject<void>();
constructor(
private _zone: NgZone,
@self()
@host()
private datepicker: MatDatepicker<any>,
) {
this._zone.runOutsideAngular(() => {
this._monitorScreenHeight$.pipe(takeUntil(this._destroy$)).subscribe(() => {
this._switchDatepickerMode();
});
});
}
ngOnInit() {
setTimeout(() => (this.datepicker.touchUi = this._isThereFreeSpace()));
}
ngOnDestroy() {
if (!!this._destroy$ && !this._destroy$.closed) {
this._destroy$.next();
this._destroy$.complete();
}
}
private _isThereFreeSpace(): boolean {
const windowHeight = this._getWindowHeight();
const inputElementRect = this.datepicker._datepickerInput
.getPopupConnectionElementRef()
.nativeElement.getBoundingClientRect();
const inputHeight = inputElementRect.height;
const freeTopSpace = inputElementRect.top;
const freeBottomSpace = windowHeight - (freeTopSpace + inputHeight);
return freeTopSpace < 354 && freeBottomSpace < 354;
}
private _switchDatepickerMode() {
const isThereFreeSpace = this._isThereFreeSpace();
if (isThereFreeSpace !== this.datepicker.touchUi) {
this._zone.run(() => (this.datepicker.touchUi = isThereFreeSpace));
}
}
private _getWindowHeight() {
return window.innerHeight
? window.innerHeight
: document.documentElement.clientHeight || document.body.clientHeight || 0;
}
}
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#6965 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AJebmUgaTLOa38c081ff6ZuB-VZmS3Ooks5uI39ggaJpZM4PSSJ->
.
|
Any progress on this? We are still facing this issue on a 13 inch laptop. I think it may need to consider right or left based on available space. On a 13 inch laptop, top or bottom is always not enough for the datepicker when its right centered in the screen! https://stackblitz.com/edit/datepicker-position-issue?file=main.ts |
@julianobrasil Yea, that would work fine on Datepicker. I was worried about any other cases where popup would be used and would need to be more smart to go right or left as well to make sure it does not cover any important information. I can not think of a usecase at the moment, so I think your fix will be fine. https://stackblitz.com/edit/datepicker-position-issue-p2xgfz
|
@mohyeid, today I spared some time to test your workaround (basically I tried it out in some situations) and there's a not so good effect when the user scrolls the screen vertically to see the calendar, as it ( |
HI Property is missing _isThereFreeSpace() can u updated ? |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Bug, feature request, or proposal:
Bug.
What is the expected behavior?
(Not sure) If there's no space in the screen nor bellow neither above to show the entire calendar, the bellow position should be the chosen one, so the user could scroll down if necessary (the scrollbar should be shown in this case).
Even better, when there's not enough screen space nor above neither bellow (but enough space in visible browser window viewport) the calendar could be shifted from its base position (defined by the the current rules) trying to fit itself in the available space. But the offset would be limited by the associated input (the input underline should fall in the space between the top and bottom edges of the calendar). Finally, when the total visible screen space wasn't enough to fit the calendar, it would end up in the bellow position, and the scrollbar would be visible.
What is the current behavior?
Notice that the top of the calendar was cropped in the images bellow and there's no scrollbar so one can see the hidden part of it (in fact, there's not viewport above to be scrolled to reveal the hidden part). And it looks like there is space to show it (first image) if it's given an offset.
IMAGE 1:
IMAGE 2:
IMAGE 3:
What are the steps to reproduce?
What is the use-case or motivation for changing an existing behavior?
Better user experience when working in not-full-screen/small windows
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
@angular/cli: 1.4.0
node: 6.10.3
os: win32 x64
@angular/animations: 4.3.6
@angular/cdk: 2.0.0-beta.10
@angular/common: 4.3.6
@angular/compiler: 4.3.6
@angular/core: 4.3.6
@angular/flex-layout: 2.0.0-beta.9-5f198a3
@angular/forms: 4.3.6
@angular/http: 4.3.6
@angular/material: 2.0.0-beta.10
@angular/platform-browser: 4.3.6
@angular/platform-browser-dynamic: 4.3.6
@angular/platform-server: 4.3.6
@angular/router: 4.3.6
@angular/cli: 1.4.0
@angular/compiler-cli: 4.3.6
@angular/language-service: 4.3.6
typescript: 2.3.4
The text was updated successfully, but these errors were encountered: