Angular Material: BreakpointObserver 无法加载?
Angular Material: BreakpointObserver not available from load?
在将 Angular BreakpointObserver
与 Angular Material
结合使用时,我尝试使用 Material 设计规范断点(它们在 Breakpoints
,例如 Breakpoints.LandscapePortrait
、Breakpoints.HandsetPortrait
).
breakpointObserver 有效,但我刚加载页面时除外。 breakpointObserver 仅在 观察到变化后触发,但考虑到它是新负载,目前还没有变化。这意味着初始视口尚未根据断点进行评估。我试过在 OnInit
中使用单个 BreakpointObserver.isMatched
,但这似乎没有任何效果。
我将 BreakpointObserver
、Breakpoints
和 MediaMatcher
包含到共享服务中,我订阅了所有需要 "listen" 到断点的组件。
我的问题是:如何确保在第一次视口更改之前评估断点(如果用户不调整 window/change 设备方向,这可能根本不会发生)?
这是我的代码 shared.service.ts
:
import {Component, OnDestroy, OnInit, Injectable,Input,Output,EventEmitter} from '@angular/core';
import {BreakpointObserver, Breakpoints, MediaMatcher} from '@angular/cdk/layout';
@Injectable()
export class SharedService implements OnDestroy, OnInit {
public isCollapsed = false;
public isOpen = false;
public isMobileView = false;
public isTabletView = false;
private breakpointObserver: BreakpointObserver;
@Output() mediaChange = new EventEmitter();
constructor(breakpointObserver: BreakpointObserver) {
this.breakpointObserver = breakpointObserver;
// check if the viewport matches Material Design-spec handset displays
this.breakpointObserver.observe([
Breakpoints.HandsetPortrait
]).subscribe(result => {
if (result.matches) {
this.isMobileView = true;
this.isTabletView = false;
this.isOpen = false;
this.isCollapsed = false;
}
else {
this.isMobileView = false;
this.isOpen = true;
this.isCollapsed = false;
}
this.mediaChanged();
});
// check if the viewport matches Material Design-spec tablet displays
this.breakpointObserver.observe([
Breakpoints.TabletPortrait
]).subscribe(result => {
if (result.matches) {
this.isTabletView = true;
this.isMobileView = false;
this.isOpen = true;
this.isCollapsed = true;
}
else {
if(!this.isMobileView){
this.isOpen = true;
}
this.isTabletView = false;
this.isCollapsed = false;
}
this.mediaChanged();
});
}
mediaChanged() {
this.mediaChange.emit({
"isMobileView" : this.isMobileView,
"isTabletView" : this.isTabletView,
"isCollapsed" : this.isCollapsed,
"isOpen" : this.isOpen
});
}
ngOnInit() {
// MY ATTEMPT
// Running the same checks as the observer, but this time on init(?)
// does not seem to take any effect
if(this.breakpointObserver.isMatched([
Breakpoints.HandsetPortrait
])){
this.isMobileView = true;
this.isTabletView = false;
this.isOpen = false;
this.isCollapsed = false;
}
if(this.breakpointObserver.isMatched([
Breakpoints.TabletPortrait
])){
this.isTabletView = true;
this.isMobileView = false;
this.isOpen = true;
this.isCollapsed = true;
}
this.mediaChanged();
}
}
将局部变量设置为 false 并根据订阅中的值更改它。
import { Component, OnInit } from '@angular/core';
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-main-menu',
templateUrl: './main-menu.component.html',
styleUrls: ['./main-menu.component.css']
})
export class MainMenuComponent implements OnInit {
isHandset = false;
constructor(private breakpointObserver: BreakpointObserver, private route: ActivatedRoute) {}
ngOnInit() {
this.breakpointObserver.observe(Breakpoints.Handset)
.subscribe((state: BreakpointState) => {
if (state.matches) {
this.isHandset = true;
} else {
this.isHandset = false;
}
});
}
}
模板代码:
<mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="isHandset ? 'dialog' : 'navigation'"
[mode]="isHandset ? 'over' : 'side'"
[opened]="isHandset === false">
<mat-toolbar>Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href="#">Link 1</a>
<a mat-list-item href="#">Link 2</a>
<a mat-list-item href="#">Link 3</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">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>timplaw-dotcom</span>
</mat-toolbar>
<!-- Add Content Here -->
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
在将 Angular BreakpointObserver
与 Angular Material
结合使用时,我尝试使用 Material 设计规范断点(它们在 Breakpoints
,例如 Breakpoints.LandscapePortrait
、Breakpoints.HandsetPortrait
).
breakpointObserver 有效,但我刚加载页面时除外。 breakpointObserver 仅在 观察到变化后触发,但考虑到它是新负载,目前还没有变化。这意味着初始视口尚未根据断点进行评估。我试过在 OnInit
中使用单个 BreakpointObserver.isMatched
,但这似乎没有任何效果。
我将 BreakpointObserver
、Breakpoints
和 MediaMatcher
包含到共享服务中,我订阅了所有需要 "listen" 到断点的组件。
我的问题是:如何确保在第一次视口更改之前评估断点(如果用户不调整 window/change 设备方向,这可能根本不会发生)?
这是我的代码 shared.service.ts
:
import {Component, OnDestroy, OnInit, Injectable,Input,Output,EventEmitter} from '@angular/core';
import {BreakpointObserver, Breakpoints, MediaMatcher} from '@angular/cdk/layout';
@Injectable()
export class SharedService implements OnDestroy, OnInit {
public isCollapsed = false;
public isOpen = false;
public isMobileView = false;
public isTabletView = false;
private breakpointObserver: BreakpointObserver;
@Output() mediaChange = new EventEmitter();
constructor(breakpointObserver: BreakpointObserver) {
this.breakpointObserver = breakpointObserver;
// check if the viewport matches Material Design-spec handset displays
this.breakpointObserver.observe([
Breakpoints.HandsetPortrait
]).subscribe(result => {
if (result.matches) {
this.isMobileView = true;
this.isTabletView = false;
this.isOpen = false;
this.isCollapsed = false;
}
else {
this.isMobileView = false;
this.isOpen = true;
this.isCollapsed = false;
}
this.mediaChanged();
});
// check if the viewport matches Material Design-spec tablet displays
this.breakpointObserver.observe([
Breakpoints.TabletPortrait
]).subscribe(result => {
if (result.matches) {
this.isTabletView = true;
this.isMobileView = false;
this.isOpen = true;
this.isCollapsed = true;
}
else {
if(!this.isMobileView){
this.isOpen = true;
}
this.isTabletView = false;
this.isCollapsed = false;
}
this.mediaChanged();
});
}
mediaChanged() {
this.mediaChange.emit({
"isMobileView" : this.isMobileView,
"isTabletView" : this.isTabletView,
"isCollapsed" : this.isCollapsed,
"isOpen" : this.isOpen
});
}
ngOnInit() {
// MY ATTEMPT
// Running the same checks as the observer, but this time on init(?)
// does not seem to take any effect
if(this.breakpointObserver.isMatched([
Breakpoints.HandsetPortrait
])){
this.isMobileView = true;
this.isTabletView = false;
this.isOpen = false;
this.isCollapsed = false;
}
if(this.breakpointObserver.isMatched([
Breakpoints.TabletPortrait
])){
this.isTabletView = true;
this.isMobileView = false;
this.isOpen = true;
this.isCollapsed = true;
}
this.mediaChanged();
}
}
将局部变量设置为 false 并根据订阅中的值更改它。
import { Component, OnInit } from '@angular/core';
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-main-menu',
templateUrl: './main-menu.component.html',
styleUrls: ['./main-menu.component.css']
})
export class MainMenuComponent implements OnInit {
isHandset = false;
constructor(private breakpointObserver: BreakpointObserver, private route: ActivatedRoute) {}
ngOnInit() {
this.breakpointObserver.observe(Breakpoints.Handset)
.subscribe((state: BreakpointState) => {
if (state.matches) {
this.isHandset = true;
} else {
this.isHandset = false;
}
});
}
}
模板代码:
<mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="isHandset ? 'dialog' : 'navigation'"
[mode]="isHandset ? 'over' : 'side'"
[opened]="isHandset === false">
<mat-toolbar>Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href="#">Link 1</a>
<a mat-list-item href="#">Link 2</a>
<a mat-list-item href="#">Link 3</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">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>timplaw-dotcom</span>
</mat-toolbar>
<!-- Add Content Here -->
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>