2016-10-29 2 views
4

Я хотел бы открыть md-sidenav на большом экране и закрыть его на мобильном устройстве. Каким будет правильный способ сделать это в моем приложении?Материал2: Показать/скрыть md-sidenav в зависимости от носителя

Есть ли возможность запросить материал внутри углового компонента?

+0

удалось вам выяснить это? Я просто столкнулся с этой самой проблемой с моим приложением ... – Narxx

+0

@Narxx просто предоставил вам возможное решение – Alex

+0

На самом деле, я подумал об этом вчера для себя ... Я могу поделиться своим решением с вами, если вам интересно: -) – Narxx

ответ

7

Внутри класса компонентов я определил ссылку на 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 
    } 
    } 
+0

Ницца! Отличное решение. Благодарю. – CENT1PEDE

1

У нас есть компонент панели инструментов, который является контейнером макета для всего приложения.

dashboard.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 из приборной панели на панели инструментов (и sidenav) компонентов с помощью шаблона с помощью [screenWidth]="screenWidth".

dashboard.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(), а затем он также будет доступен в шаблоне дочернего компонента.

toolbar.ts:

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

Это позволит шаблону панели инструментов, чтобы иметь доступ к screenWidth переменным, определенным ранее в приборной панели, и получать обновления каждый раз, когда она меняется (так что вы можете установить логика один раз в приборной панели и наследуют это значение во всем мире через приложение

toolbar.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> 
+0

ОК, вы также реагируете на окно: изменение размера события и использование window.innerWidth для решения проблемы. это ключ к решению – Alex

+0

Я не знаю, является ли это лучшей практикой, но это то, чем мы закончили. Еще за дополнительные предложения, если кто-нибудь увидит эту тему в будущем ... – Narxx

+0

не забывайте, что Angular Material 2 все еще является альфа ... – Alex

1

Я нашел решение сюда m другой пост: rxjs/behaviorsubject.

Вы можете получить значение ширины из BehaviorSubject.window. И я использую его вместо этого, чтобы переключить режим sidenav между «side» и «over».

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

component.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" 
     } 
     } 
    }); 
} 
0

я только что нашел немного лучше подход слушать изменения экрана в Угловое: https://github.com/angular/flex-layout/wiki/ObservableMedia

Это Угловой модуль Flex, который обеспечивает уведомления о активации mediaQuery как наблюдаемые. поэтому нет необходимости слушать, чтобы создать прослушиватель resize вручную.

кроме того, MediaChange Class предоставляет удобные псевдонимы (lg, md, xs и т.д.), которые могут быть использованы для принятия решений о выражениях размера конкретного экрана.

ознакомьтесь с примерами на своей вики-странице.

0

Я решил этот тот же самый вопрос сегодня на своем рабочем месте. Я сделал это в основном, используя тот же подход, что @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 :)