Когда я загружаю страницу с компонентом Сиденав, меню слева закрывается. Как сделать так, чтобы меню открывалось по умолчанию и только после уменьшения ширины окна появлялась кнопка бургера, а само меню сворачивалось? Я хочу сделать то же самое https://material.angular.io/components/categories
Я создаю новый компонент, используя эту команду:
ng generate @angular/material:nav <component-name>
(https://material.angular.io/guide/schematics)
navigation.component.html
<mat-sidenav-container class = "sidenav-container">
<mat-sidenav #drawer class = "sidenav" fixedInViewport
[attr.role] = "(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode] = "(isHandset$ | async) ? 'over' : 'side'"
[opened] = "(isHandset$ | async) === false">
<mat-toolbar>Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href = "/about">About</a>
<a mat-list-item href = "/contact">Contact</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color = "primary">
<button
type = "button"
aria-label = "Toggle sidenav"
mat-icon-button
(click) = "drawer.toggle()"
*ngIf = "isHandset$ | async">
<mat-icon aria-label = "Side nav toggle icon">menu</mat-icon>
</button>
<span>NavApp</span>
</mat-toolbar>
<router-outlet></router-outlet>
<!-- Add Content Here -->
</mat-sidenav-content>
</mat-sidenav-container>
navigation.component.ts
import { Component } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Observable } from 'rxjs';
import { map, share } from 'rxjs/operators';
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss']
})
export class NavigationComponent {
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches),
share()
);
constructor(private breakpointObserver: BreakpointObserver) {}
}
когда я пытаюсь изменить [opened]="true" левое меню открывается, но нет привязки событий для this.breakpointObserver.observe(Breakpoints.Handset), и если я изменяю размер окна, левое меню не закрывается





Я считаю, что проблема заключается в том, что в вашем компоненте вы используете оператор share() для совместного использования наблюдаемого от this.breakpointObserver.observe() между четырьмя подписчиками (асинхронный канал) в вашем HTML-шаблоне.
Это означает, что этот наблюдаемый объект будет испускаться, когда он подписан на первый (в элементе <mat-sidenav>); эта эмиссия будет общей, но поскольку ваш элемент <button> имеет еще не создан, эмиссия слишком ранняя, и <button> никогда не получит ее. Это означает, что *ngIf на кнопке будет оцениваться как false при первой загрузке, даже если isHandset$ на самом деле выдал true, поэтому вы не увидите кнопку меню в мобильном представлении.
Чтобы решить эту проблему, вы можете использовать оператор shareReplay() вместо share(), который будет воспроизводить рассылку от this.breakpointObserver.observe() всем новым подписчикам (например, тому, что в <button>), даже если они были созданы после рассылки.
navigation.component.ts
import { Component } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss']
})
export class NavigationComponent {
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches),
shareReplay(1),
);
constructor(private breakpointObserver: BreakpointObserver) { }
}
@ redk0m Я понял, что решение, которое я дал, было не очень хорошим, поэтому я обновил свой ответ, добавив лучшее решение с объяснением. Мой первоначальный ответ работал аналогично новому (гарантируя, что все подписчики в вашем шаблоне получили наблюдаемое), но, как вы видите в моем новом решении, не было необходимости создавать отдельные подписки для каждого асинхронного канала в шаблоне.
Возможно, чтобы добавить к этому, если кто-то хочет наблюдать за изменением определенной ширины, замените код breakpointObserver.observe следующим:
isHandset$: Observable<boolean> = this.breakpointObserver.observe('(max-width: 720px)')
.pipe(
map(result => result.matches),
shareReplay(1),
);
можете объяснить подробнее, это действительно работает, но я не понимаю, почему