角度材料mat-sidenav异步内容区域无法呈现在正确的位置

时间:2018-02-23 20:53:23

标签: angular-material sidenav

我有一个适用于模拟数据的sidenav,但是当我从休息服务异步加载sidenav的数据时,内容部分呈现在整个页面区域,然后当异步调用返回时,sidenav渲染,并最终覆盖部分内容区域。如果我关闭sidenav并再次打开,它看起来找不到。但是,在初始加载时,我无法看到内容的左侧部分。

    <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>

有关如何解决这个问题的想法吗?

2 个答案:

答案 0 :(得分:1)

我根据 Angular Materials 文档通过设置以下 MatDrawerContainer 属性修复了类似的问题(使用 MatDrawer):https://next.material.angular.io/components/sidenav/api

  • @Input() 自动调整大小:布尔值

    是否自动调整容器大小 它的任何抽屉都发生了变化。

    使用风险自负!启用此选项可能会导致布局抖动 通过在每个变化检测周期测量抽屉。可 通过 MAT_DRAWER_DEFAULT_AUTOSIZE 令牌全局配置。

就我而言:

public class EnterFullscreen extends AbstractAction{

    private static final long serialVersionUID = 1773898497666165938L;
    
    private JFrame frame;
    private boolean isHost;
    private LobbyState lobbyState;
    private Class<?> frameType;
    private Constructor<?> c;
    
    public EnterFullscreen(JFrame frame, boolean isHost, LobbyState lobbyState) {
        
        this.frame = frame;
        this.isHost = isHost;
        this.lobbyState = lobbyState;
        
        try {
            frameType = frame.getClass();
            if (frameType.equals(Lobby.class)) {
                c = frameType.getConstructor(Integer.class, Image.class, Boolean.class, LobbyState.class);  
            } else {
                c = frameType.getConstructor(Integer.class, Image.class, Boolean.class);    
            }
        } catch (SecurityException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        
        try {
            
            frame.setVisible(false);
            if (frame.isUndecorated()) {
                if (frameType.equals(Lobby.class)) {
                    c.newInstance(0, frame.getIconImage(), isHost, lobbyState);
                } else {
                    c.newInstance(0, frame.getIconImage(), isHost);
                }
            } else {
                if (frameType.equals(Lobby.class)) {
                    c.newInstance(1, frame.getIconImage(), isHost, lobbyState);
                } else {
                    c.newInstance(1, frame.getIconImage(), isHost);
                }
            }

            frame.dispose();
            
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException e1) {
            e1.printStackTrace();
        }
        
    }
    
}

答案 1 :(得分:0)

我遇到了同样的问题,我找到了一种适用于我的情况的解决方案。 首先,我需要在呈现视图后立即托管要调用mat-nav-list的组件。 为此,我选择使用指令( renderingDetector )装饰mat-nav-list。 这是代码:

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();
    }
}

注意::作为一种可能的解决方案,我还尝试将整个mat-nav-list内容移到一个单独的组件中,以控制其生命周期以及它在内部完成的过程。指令,但是这种方法会导致应用程序在我每次单击某个项目时都对页面重新充电(这样一来,单页应用程序的所有好处就会丢失)。

另一方面,托管组件一直在监视它。

<mat-nav-list renderingDetector (onViewRendered)="viewRendered()">

为了使mat-sidenav-content恰好在菜单旁边呈现,我们应该正确设置 margin-left 属性。

@ViewChild('sidenavRef') sideNavRef: MatSidenav;
@ViewChild('sidenavContentRef', {read: ElementRef}) sideNavContentRef: ElementRef;
viewRendered() {
    this.sideNavContentRef.nativeElement.style.marginLeft = String(this.sideNavRef._width) + "px";
}

sidenavRef sidenavContentRef 是指html文件中的mat-sidenav和mat-sidenav-content元素

<mat-sidenav-container>
    <mat-sidenav #sidenavRef>
        ...
    </mat-sidenav>
    <mat-sidenav-content #sidenavContentRef>
        ...
    </mat-sidenav-content>
</mat-sidenav-container>