2

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?

slarty
  • 21
  • 4
  • What's your `[disa]` attribute after ` – Edric Feb 24 '18 at 15:00
  • Good point - I'm not sure - still happens after I delete it. I found out how to force it to work though. If I put `autosize` in `mat-sidenav-container`, it works fine. However, I don't like this, since the docs warn about performance issues, and after the left nav is loaded, it won't be changing at all, so I don't want sizing to be calculated over and over. – slarty Feb 24 '18 at 17:03
  • `fullscreen` in mat-sidenav-container helped me – prisar Dec 25 '18 at 13:39

2 Answers2

4

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>
MarioMoser
  • 41
  • 2
0

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>