8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

由于 app.component 中的可观察对象,Angular mat-sidenav 最初覆盖了 nav-content

Maselia 2月前

55 0

我正在使用一个 mat-sidenav-container,它包含一个 mat-sidenav 和一个 mat-sidenav-content。mat-sidenav 有一些链接,这些链接应该根据我的 app.component.ts 中的布尔值显示。

我正在使用 mat-sidenav-container 包含 mat-sidenav 和的 mat-sidenav-content .

mat-sidenav 一些链接应该根据我的 app.component.ts 中的布尔值显示。因此,渲染过程中会出现问题,侧边导航会绘制在内容之上,而不是将内容渲染到侧边导航的右侧。

例子:

enter image description here

读了一会儿之后,关于这个话题的抱怨越来越多。我 在这里 ,解决这个问题的办法是使用 autosize 上的属性 mat-sidenav-container ,但它带来了一些问题, 这里 .

因此,我开始尝试在 github 页面上提出的另一个建议,以“重置”模式 mat-sidenav .

这有效,但只有当我添加延迟时才有效。

应用程序.组件.html

  async ngOnInit() {
    this.isLoggedIn = await this.authService.isLoggedIn();
    this.isAdmin = await this.authService.isAdmin();
    console.log("app started");
    // when I add a delay of zero milliseconds, my sidenav content is drawn correctly??? 
    //await delayMilliseconds(0);
    this.sidenav.mode = 'side';
  }

为了完整性实施 delayMilliseconds

export function delayMilliseconds(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
}

那么 mat-sidenav 的黑暗到底是怎么回事?我不介意保留我当前的 \'hack\' 并将延迟设置为零,但我最想更好地理解为什么在没有延迟的情况下会出现问题。或者更确切地说,为什么不重置模式就无法正常工作。这真的是一个错误还是我做错了什么?

为了完整性,整个 app.component.html

<mat-toolbar color="primary">
  <button mat-icon-button class="example-icon" aria-label="Example icon-button with menu icon" (click)="sidenav.toggle()">
    <mat-icon>menu</mat-icon>
  </button>
  <span style="margin-left: 5px;">{{title}}</span>
  <span class="example-spacer"></span>
  <button *ngIf="isLoggedIn" type="button" (click)="logout()">
    <mat-icon>logout</mat-icon>
  </button>
  <button *ngIf="!(isLoggedIn)" type="button" (click)="login()">
    <mat-icon>login</mat-icon>
  </button>
</mat-toolbar>

<mat-sidenav-container style="height:100vh;">
  <mat-sidenav #sidenav mode="side" opened="true">
    <mat-nav-list>
      <a mat-list-item routerLink="/home">Home</a>
      <a *ngIf="isLoggedIn" mat-list-item routerLink="/dashboard">Dashboard</a>
      <a *ngIf="isLoggedIn" mat-list-item routerLink="/customers">Customers</a>
      <a *ngIf="isLoggedIn" mat-list-item routerLink="/projects">Projects</a>
      <a *ngIf="isLoggedIn" mat-list-item routerLink="/usersettings">User settings</a>
      <a *ngIf="isAdmin" mat-list-item routerLink="/admin">Admin</a>
    </mat-nav-list>
  </mat-sidenav>

  <mat-sidenav-content style="padding-top: 0px; padding-left: 20px; padding-right: 20px;">
    <router-outlet ></router-outlet>
  </mat-sidenav-content>
</mat-sidenav-container>

以及完整的 app.compoment.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { AuthService } from "./auth-service";
import { CustomerService } from './customer-service';
import { KeycloakProfile } from 'keycloak-js';
import { MatSidenav } from '@angular/material/sidenav';
import { delayMilliSeconds as delayMilliseconds } from 'src/common/utils/delay';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  @ViewChild('sidenav') sidenav: MatSidenav;

  title = 'Projects buddy';
  public isLoggedIn : boolean;
  public userProfile: KeycloakProfile | null = null;
  isAdmin = false ;

  constructor(
    private readonly authService : AuthService,
    private customerService : CustomerService,
    ) {}

  async ngOnInit() {
    this.isLoggedIn = await this.authService.isLoggedIn();
    this.isAdmin = await this.authService.isAdmin();
    console.log("app started");
    await delayMilliseconds(0);
    this.sidenav.mode = 'side';
  }

  async login() {
    if (!this.isLoggedIn) {
      console.log("logging in keycloak");
      await this.authService.login();
    }
  }

  async logout() {
    if (this.isLoggedIn) {
      console.log("logging off keycloak");
      await this.authService.logoff();  
    }
  }
}

结束语

  • 没有\'奇怪的黑客\' mat-nav-list 绘制在顶部 mat-nav-content
  • 第一个解决方法是添加到 autosize mat-sidenav-container 但官方文档中的布局破坏警告让我不敢采用这种方法
  • 重置模式的第二种解决方法 mat-sidenav 似乎仅在我添加零延迟时才有效,这没有意义,但我还是尝试了。
  • 这种奇怪的行为真的是由角度材料中的错误引起的吗?还是我以错误的方式使用了它们的组件?有什么建议可以改善/解决这个问题吗?
帖子版权声明 1、本帖标题:由于 app.component 中的可观察对象,Angular mat-sidenav 最初覆盖了 nav-content
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Maselia在本站《angular》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 据我所知,侧边导航组件需要知道其尺寸才能正确渲染。您的 hack 之所以有效,是因为你实际上使用以下方式触发了新的渲染检查:

  • 该问题主要归因于涉及动态条件时渲染和布局重新计算的时间。通过使用 autosize 属性、手动触发更改检测或使用以下方法推迟初始化:

  • 我正在使用 Angular 并尝试在 effect() 中使用信号。我的目标是在特定信号发生变化时触发操作,但操作本身不需要信号的值。例如...

    我正在使用 Angular 并尝试在 中使用信号 effect() 。我的目标是在特定信号发生变化时触发操作,但操作本身不需要信号的值。

    例如,我有一个 isAuthorized 信号,并且我想 fetchCars() 在授权状态改变时调用它,但 fetchCars() 不需要使用 isAuthorized 值。

    constructor() {
      effect(() => {
        const isAuthorized = this.authService.userAuthorized();
        
        // This function doesn't use the value of isAuthorized anyway.
        this.fetchCars();
      });
    }
    

    如果不实际使用它就将其分配给常量, isAuthorized 这有点奇怪

    角度版本:18.0.1

  • 您可以使用 toObservable() 将信号转换为 Observable:

    constructor() {
      toObservable(this.authService.userAuthorized)
        .pipe(takeUntilDestroyed())
        .subscribe(() => this.fetchCars())
    }
    

    toObservable RxJS Interop 包 的一部分 ,目前处于 开发人员预览阶段 ,在稳定之前可能会发生(重大)变化。

  • eqzx 2月前 0 只看Ta
    引用 6

    注意:在撰写本文时,Angular Signal RxJS Interop 包处于开发者预览版中。

  • @MichaelD 效果也在开发者预览版中,所以我认为这不应该是个问题。但绝对值得一提,我会将其添加到答案中。谢谢!

  • 我找不到比使用 toObservable() @JSONDerulo 提到的方法或触发信号获取器 effect() .

    但是,您可以在触发信号获取器的服务中定义一个命名的效果变量,这样您不必在每个使用该效果的组件中触发它。

    尝试以下操作

    服务

    import { Injectable, signal, effect } from '@angular/core';
    
    @Injectable({
      providedIn: 'root',
    })
    export class AuthService {
      public readonly userAuthorized = signal(false);
      public readonly userAuthorizedEffect = (callback: () => void) =>
        effect(() => {
          this.userAuthorized();
          callback();
        });
    
      public toggleAuthStatus(): void {
        this.userAuthorized.set(!this.userAuthorized());
      }
    }
    

    成分

    export class App {
      constructor(private readonly authService: AuthService) {
        this.authService.userAuthorizedEffect(() => {
          this.fetchCars();
        });
      }
    
      fetchCars() {
        console.log('fetching cars here...');
      }
    }
    

    工作示例: Stackblitz

返回
作者最近主题: