Reputation: 21
I have a sidenav that works great with mock data, but when I load the data for the sidenav asynchronously from a rest service, the content part renders on the entire page area, and then when the async call returns, the sidenav renders, and ends up covering part of the content area. If I close the sidenav and open again, it looks find. However, on initial load, I can't see the left part of the content.
<mat-sidenav-container fullscreen class="main-sidenav-container">
<mat-sidenav #sidenav mode="side" opened>
<mat-nav-list>
<mat-list-item disa *ngFor="let navBarItem of observableNavBarItems|async" (click)="onSelected(navBarItem.value)">
<img mat-list-icon class="{{navBarItem.icon}}" />
<h4 mat-line>{{navBarItem.name}}</h4>
</mat-list-item>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
Any thoughts on how to fix this?
Upvotes: 2
Views: 2099
Reputation: 61
i fixed a similar Problem (using the MatDrawer) by setting the following MatDrawerContainer property according to the Angular Materials documentation: https://next.material.angular.io/components/sidenav/api
@Input() autosize: boolean
Whether to automatically resize the container whenever the size of any of its drawers changes.
Use at your own risk! Enabling this option can cause layout thrashing by measuring the drawers on every change detection cycle. Can be configured globally via the MAT_DRAWER_DEFAULT_AUTOSIZE token.
in my case:
<mat-drawer-container autosize="true" >
<mat-drawer #drawer mode="side" opened="true">
...
</mat-drawer>
<mat-drawer-content>
...
</mat-drawer-content>
</mat-drawer-container>
Upvotes: 6
Reputation: 1
i had the same problem and i've found a solution that works fine in my case. First of all, i needed my component hosting the mat-nav-list being invoked as soon as its view had been rendered. In order to do this, i choose to decorate mat-nav-list with a directive (renderingDetector). Here is the code:
import { Directive, AfterViewInit, Output, EventEmitter } from '@angular/core';
@Directive({
selector: '[renderingDetector]'
})
export class RenderingDetectorDirective implements AfterViewInit {
@Output() onViewRendered = new EventEmitter<void>(true);
ngAfterViewInit() {
this.onViewRendered.emit();
}
}
NOTE: as a possible solution, i also tried to move the whole mat-nav-list content into a separate component in order to control its life-cycle as well as it's been done inside the directive, but this approach headed to the application recharging the page every time i clicked on an item (so that all benefits of Single Page Application went lost).
On the other side, the hosting component keeps watching on it.
<mat-nav-list renderingDetector (onViewRendered)="viewRendered()">
In order to have the mat-sidenav-content being rendered exactly beside the menus we should properly set the margin-left property.
@ViewChild('sidenavRef') sideNavRef: MatSidenav;
@ViewChild('sidenavContentRef', {read: ElementRef}) sideNavContentRef: ElementRef;
viewRendered() {
this.sideNavContentRef.nativeElement.style.marginLeft = String(this.sideNavRef._width) + "px";
}
sidenavRef and sidenavContentRef refer to the mat-sidenav and mat-sidenav-content elements in the html file
<mat-sidenav-container>
<mat-sidenav #sidenavRef>
...
</mat-sidenav>
<mat-sidenav-content #sidenavContentRef>
...
</mat-sidenav-content>
</mat-sidenav-container>
Upvotes: 0