5

我想在大屏幕上打开md-sidenav并在移动设备上关闭它。在我的应用程序中执行此操作的正确方法是什么?

是否有可能查询 angular2 组件内的媒体?

4

5 回答 5

8

在组件类内部,我定义了对 sidenav 的引用并监听窗口调整大小事件。根据 window.innerWith 您可以构建您的逻辑。

  @ViewChild('sidenav') sidenav: MdSidenav

  @HostListener('window:resize', ['$event'])
  onResize(event) {
    this.configureSideNav()
  }

  configureSideNav() {
    this.smallScreen = window.innerWidth < 501 ? true : false
    if (!this.smallScreen) {
      this.sidenav.mode = "side"
      this.sidenav.opened = true
    } else {
      this.sidenav.mode = 'over'
      this.sidenav.opened = false
    }
  }
于 2016-11-28T21:58:49.757 回答
5

我刚刚找到了一种更好的方法来收听 Angular 中的屏幕变化:https ://github.com/angular/flex-layout/wiki/ObservableMedia

它是一个Angular Flex 布局模块,提供可观察的 mediaQuery 激活通知。所以无需resize手动创建监听器。

此外,MediaChangeClass 提供了方便的别名(lgmdxs),可用于决定屏幕大小特定的表达式。

在他们的 wiki 页面上查看示例。

于 2017-06-06T17:36:45.777 回答
3

我们有一个仪表板组件,它是整个应用程序的布局容器。

仪表板.html:

<md-sidenav-layout class="sidenav-layout">

  <bv-toolbar (toggleSidenav)="start.toggle()" [screenWidth]="screenWidth"></bv-toolbar>
  <md-sidenav #start [opened]="screenWidth > 1000" [mode]="(screenWidth > 1000) ? 'side' : 'start'">
    <bv-sidenav-content  [user]="user$ | async" [screenWidth]="screenWidth" (navClose)="start.toggle()"></bv-sidenav-content>
  </md-sidenav>

  <div class="sidenav-content"></div>
</md-sidenav-layout>

请注意我们如何通过模板使用[screenWidth]="screenWidth".

仪表板.ts:

...
export class DashboardComponent {
  screenWidth: number;
...
constructor (private cdr: ChangeDetectorRef, private store: Store<fromRoot.State> ) {

  var that = this;
  // set screenWidth on page load
  that.screenWidth = window.innerWidth;
  window.onresize = () => {
    // set screenWidth on screen size change
    that.screenWidth = window.innerWidth;
    that.cdr.detectChanges();
  }
}

现在screenWidth在我们的仪表板上设置,并通过模板发送到其他组件,我们需要在子组件的脚本中接收它,@Input()然后它也将在子组件的模板中可用。

工具栏.ts:

...
export class ToolbarComponent {
  @Output() toggleSidenav = new EventEmitter();
  @Input() screenWidth : number;
}

这将允许工具栏的模板访问screenWidth前面在仪表板中定义的变量,并在每次更改时获取更新(因此您可以在仪表板中设置一次逻辑并在整个应用程序的任何地方继承该值。

工具栏.html:

<md-toolbar color="primary">
  <button md-icon-button
          (click)="toggleSidenav.emit()"
          [ngClass]="{'h-hide': screenWidth > 1000}">
      <md-icon>menu</md-icon>
  </button>
</md-toolbar>
于 2016-12-04T10:41:28.490 回答
1

我今天在工作场所解决了同样的问题。我基本上使用@AndyGrey 指出的相同方法完成了它。我认为代码示例可能会对某人有所帮助。

sidenav-layout.component.ts

    import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
    import { ObservableMedia, MediaChange } from '@angular/flex-layout';
    import { MdSidenav } from '@angular/material';
    import { Subscription } from 'rxjs/Subscription';

    @Component({
      selector: 'sidenav-layout',
      templateUrl: './sidenav-layout.component.html',
      styleUrls: [ './sidenav-layout.component.scss' ]
    })

    export class SidenavLayoutComponent implements OnInit, OnDestroy {

      @ViewChild('sidenav') sidenav: MdSidenav;

      private _mediaSubscription: Subscription;
      sidenavOpen = true;
      isMobile = false;

      constructor(private media: ObservableMedia) {}

      ngOnInit() {
        this._mediaSubscription = this.media.asObservable().subscribe((change: 
     MediaChange) => {
      this.isMobile = (change.mqAlias === 'xs') || (change.mqAlias === 'sm');
      this.sidenavOpen = !this.isMobile;
    });
  }

  onLinkClick() {
    if (this.isMobile) {
      this.sidenav.toggle();
    }
  }

  ngOnDestroy() {
    this._mediaSubscription.unsubscribe();
  }
}

sidenav-layout.component.html

 <md-sidenav #sidenav mode="side" opened={{sidenavOpen}}>

onLinkClick() 方法应该添加到您的所有列表项中。因此,每当在移动视图中单击链接时,sidenav 都会被切换(隐藏)。

最后别忘了取消订阅 mediaSubscription Observable :)

于 2017-06-22T00:06:41.767 回答
1

我从另一篇文章中找到了解决方案:rxjs/behaviorsubject

您可以从 BehaviorSubject.window 中获取宽度的值。而我用它来在“side”和“over”之间切换sidenav模式。

windows.service.ts:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class WindowService {
    public window = new BehaviorSubject(null);

    public width: Observable<number>;

    constructor() {
        let windowSize = new BehaviorSubject(getWindowSize());

        this.width = (windowSize.pluck('width') as Observable<number>).distinctUntilChanged();

        Observable.fromEvent(window, 'resize')
            .map(getWindowSize)
            .subscribe(windowSize);
    }


}

function getWindowSize() {
    return {
        width: window.innerWidth
    };
}

组件.ts:

ngOnInit() {
    // Change sideNav mode between over and side depending on size of window
    this.windowService.width.subscribe((width) => {
      if (width) {
        console.log(width);
        if (width < 600) {
          this.sideNavMode = "over"
        } else {
          this.sideNavMode = "side"
        }
      }
    });
}
于 2017-03-13T23:12:13.383 回答