Skip to content

refactor(sidenav): expose api to update content margins #15833

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

Merged
merged 1 commit into from
May 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 56 additions & 57 deletions src/material/sidenav/drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -541,15 +541,15 @@ export class MatDrawerContainer implements AfterContentInit, DoCheck, OnDestroy
if (_dir) {
_dir.change.pipe(takeUntil(this._destroyed)).subscribe(() => {
this._validateDrawers();
this._updateContentMargins();
this.updateContentMargins();
});
}

// Since the minimum width of the sidenav depends on the viewport width,
// we need to recompute the margins if the viewport changes.
viewportRuler.change()
.pipe(takeUntil(this._destroyed))
.subscribe(() => this._updateContentMargins());
.subscribe(() => this.updateContentMargins());

this._autosize = defaultAutosize;
}
Expand All @@ -567,7 +567,7 @@ export class MatDrawerContainer implements AfterContentInit, DoCheck, OnDestroy
if (!this._drawers.length ||
this._isDrawerOpen(this._start) ||
this._isDrawerOpen(this._end)) {
this._updateContentMargins();
this.updateContentMargins();
}

this._changeDetectorRef.markForCheck();
Expand All @@ -576,7 +576,7 @@ export class MatDrawerContainer implements AfterContentInit, DoCheck, OnDestroy
this._doCheckSubject.pipe(
debounceTime(10), // Arbitrary debounce time, less than a frame at 60fps
takeUntil(this._destroyed)
).subscribe(() => this._updateContentMargins());
).subscribe(() => this.updateContentMargins());
}

ngOnDestroy() {
Expand All @@ -596,6 +596,56 @@ export class MatDrawerContainer implements AfterContentInit, DoCheck, OnDestroy
this._drawers.forEach(drawer => drawer.close());
}

/**
* Recalculates and updates the inline styles for the content. Note that this should be used
* sparingly, because it causes a reflow.
*/
updateContentMargins() {
// 1. For drawers in `over` mode, they don't affect the content.
// 2. For drawers in `side` mode they should shrink the content. We do this by adding to the
// left margin (for left drawer) or right margin (for right the drawer).
// 3. For drawers in `push` mode the should shift the content without resizing it. We do this by
// adding to the left or right margin and simultaneously subtracting the same amount of
// margin from the other side.
let left = 0;
let right = 0;

if (this._left && this._left.opened) {
if (this._left.mode == 'side') {
left += this._left._width;
} else if (this._left.mode == 'push') {
const width = this._left._width;
left += width;
right -= width;
}
}

if (this._right && this._right.opened) {
if (this._right.mode == 'side') {
right += this._right._width;
} else if (this._right.mode == 'push') {
const width = this._right._width;
right += width;
left -= width;
}
}

// If either `right` or `left` is zero, don't set a style to the element. This
// allows users to specify a custom size via CSS class in SSR scenarios where the
// measured widths will always be zero. Note that we reset to `null` here, rather
// than below, in order to ensure that the types in the `if` below are consistent.
left = left || null!;
right = right || null!;

if (left !== this._contentMargins.left || right !== this._contentMargins.right) {
this._contentMargins = {left, right};

// Pull back into the NgZone since in some cases we could be outside. We need to be careful
// to do it only when something changed, otherwise we can end up hitting the zone too often.
this._ngZone.run(() => this._contentMarginChanges.next(this._contentMargins));
}
}

ngDoCheck() {
// If users opted into autosizing, do a check every change detection cycle.
if (this._autosize && this._isPushed()) {
Expand All @@ -621,7 +671,7 @@ export class MatDrawerContainer implements AfterContentInit, DoCheck, OnDestroy
this._element.nativeElement.classList.add('mat-drawer-transition');
}

this._updateContentMargins();
this.updateContentMargins();
this._changeDetectorRef.markForCheck();
});

Expand Down Expand Up @@ -653,7 +703,7 @@ export class MatDrawerContainer implements AfterContentInit, DoCheck, OnDestroy
if (drawer) {
drawer._modeChanged.pipe(takeUntil(merge(this._drawers.changes, this._destroyed)))
.subscribe(() => {
this._updateContentMargins();
this.updateContentMargins();
this._changeDetectorRef.markForCheck();
});
}
Expand Down Expand Up @@ -730,55 +780,4 @@ export class MatDrawerContainer implements AfterContentInit, DoCheck, OnDestroy
return drawer != null && drawer.opened;
}

/**
* Recalculates and updates the inline styles for the content. Note that this should be used
* sparingly, because it causes a reflow.
*/
private _updateContentMargins() {
// 1. For drawers in `over` mode, they don't affect the content.
// 2. For drawers in `side` mode they should shrink the content. We do this by adding to the
// left margin (for left drawer) or right margin (for right the drawer).
// 3. For drawers in `push` mode the should shift the content without resizing it. We do this by
// adding to the left or right margin and simultaneously subtracting the same amount of
// margin from the other side.

let left = 0;
let right = 0;

if (this._left && this._left.opened) {
if (this._left.mode == 'side') {
left += this._left._width;
} else if (this._left.mode == 'push') {
let width = this._left._width;
left += width;
right -= width;
}
}

if (this._right && this._right.opened) {
if (this._right.mode == 'side') {
right += this._right._width;
} else if (this._right.mode == 'push') {
let width = this._right._width;
right += width;
left -= width;
}
}

// If either `right` or `left` is zero, don't set a style to the element. This
// allows users to specify a custom size via CSS class in SSR scenarios where the
// measured widths will always be zero. Note that we reset to `null` here, rather
// than below, in order to ensure that the types in the `if` below are consistent.
left = left || null!;
right = right || null!;

if (left !== this._contentMargins.left || right !== this._contentMargins.right) {
this._contentMargins = {left, right};

// Pull back into the NgZone since in some cases we could be outside. We need to be careful
// to do it only when something changed, otherwise we can end up hitting the zone too often.
this._ngZone.run(() => this._contentMarginChanges.next(this._contentMargins));
}

}
}
1 change: 1 addition & 0 deletions tools/public_api_guard/material/sidenav.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export declare class MatDrawerContainer implements AfterContentInit, DoCheck, On
ngDoCheck(): void;
ngOnDestroy(): void;
open(): void;
updateContentMargins(): void;
}

export declare class MatDrawerContent extends CdkScrollable implements AfterContentInit {
Expand Down