Открыть/закрыть сиденав из другого компонента
Я использую angular (последняя версия) и angular материал.
Есть 3 компонента:
- header.component, в котором есть кнопка управления справа-sidenav
- rigth-sidenav.component, в котором есть право-sidenav
- sidenav.component (это левое главное меню), этот компонент вызывает header.component, right-sidenav.component и контент
Как открыть/закрыть сиденав из другого компонента? (в моем случае кнопка находится в header.component).
Попробовал следующий вариант (но получил ошибку: TypeError: this.RightSidenavComponent.rightSidenav не определен):
header.component.html
<button mat-button (click)="toggleRightSidenav()">Toggle side nav</button>
header.component.ts
import { Component } from '@angular/core';
import { RightSidenavComponent } from '../right-sidenav/right-sidenav.component';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent {
constructor(public RightSidenavComponent:RightSidenavComponent) { }
toggleRightSidenav() {
this.RightSidenavComponent.rightSidenav.toggle();
}
}
sidenav.component.html
<mat-sidenav-container class="sidenav-container">
<mat-sidenav #sidenav mode="side" opened="true" class="sidenav"
[fixedInViewport]="true"> Sidenav </mat-sidenav>
<mat-sidenav-content>
<app-header></app-header>
<router-outlet></router-outlet>
<app-right-sidenav #rSidenav></app-right-sidenav>
</mat-sidenav-content>
</mat-sidenav-container>
sidenav.component.ts
import { Component, Directive, ViewChild } from '@angular/core';
import { RightSidenavComponent } from '../right-sidenav/right-sidenav.component';
@Component({
selector: 'app-sidenav',
templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.scss']
})
export class SidenavComponent {
@ViewChild('rSidenav') public rSidenav;
constructor(public RightSidenavComponent: RightSidenavComponent) {
this.RightSidenavComponent.rightSidenav = this.rSidenav;
}
}
правой sidenav.component.html
<mat-sidenav #rightSidenav mode="side" opened="true" class="rightSidenav"
[fixedInViewport]="true" [fixedTopGap]="250">
Sidenav
</mat-sidenav>
правой sidenav.component.ts
import { Component, Injectable } from '@angular/core';
@Component({
selector: 'app-right-sidenav',
templateUrl: './right-sidenav.component.html',
styleUrls: ['./right-sidenav.component.scss']
})
@Injectable()
export class RightSidenavComponent {
public rightSidenav: any;
constructor() { }
}
Нерабочий пример с кодом stackblitz
Ответы
Ответ 1
У меня была такая же проблема с использованием. Я решил это так.
SidenavService
import { Injectable } from '@angular/core';
import { MatSidenav } from '@angular/material';
@Injectable()
export class SidenavService {
private sidenav: MatSidenav;
public setSidenav(sidenav: MatSidenav) {
this.sidenav = sidenav;
}
public open() {
return this.sidenav.open();
}
public close() {
return this.sidenav.close();
}
public toggle(): void {
this.sidenav.toggle();
}
Ваш компонент
constructor(
private sidenav: SidenavService) { }
toggleRightSidenav() {
this.sidenav.toggle();
}
Свяжите свой HTML toggle() в соответствии с вашими требованиями.
Компонент приложения.
@ViewChild('sidenav') public sidenav: MatSidenav;
constructor(private sidenavService: SidenavService) {
}
ngOnInit(): void {
this.sidenavService.setSidenav(this.sidenav);
}
Модуль приложения
providers: [YourServices , SidenavService],
Рабочий пример с кодом stackblitz
Ответ 2
Я использовал @Input() remoteSideNav: MatSideNav
в родительском\другом компоненте для передачи объекта sideNav в качестве целевого свойства от дочернего компонента. Работает как положено. Кстати, мне понравилась реализация сервиса @Eldho :)
Child.component.html
<app-layout-header [inputSideNav]="sideNav"></app-layout-header>
<mat-sidenav-container>
<mat-sidenav #sideNav (click)="sideNav.toggle()" mode="side">
<a routerLink="/">List Products</a>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
макета header.component.html
<section>
<mat-toolbar>
<span (click)="inputSideNav.toggle()">Menu</span>
</mat-toolbar>
</section>
макета header.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { MatSidenav } from '@angular/material';
@Component({
selector: 'app-layout-header',
templateUrl: './layout-header.component.html',
styleUrls: ['./layout-header.component.css']
})
export class LayoutHeaderComponent implements OnInit {
@Input() inputSideNav: MatSidenav;
constructor() { }
ngOnInit() {
}
}
Ответ 3
Прежде всего, вам не нужно вызывать rightSideNav в компоненте sideNav.
Ваша кнопка переключения находится в компоненте заголовка.
Таким образом, вы можете сделать это в своем компоненте заголовка.
header.component.ts:
import { Component } from '@angular/core';
import { RightSidenavComponent } from '../right-sidenav/right-sidenav.component';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent {
rightSideNav : boolean ;
constructor(public RightSidenavComponent:RightSidenavComponent) { }
sideNavBtnToggle(){
if(this.rightSideNav == false)
{
this.rightSideNav = true;
}
else{
this.rightSideNav = false;
}
}
}
И в вашем header.component.html
введите этот код:
<app-right-sidenav *ngIf="rightSideNav"></app-right-sidenav>
Это облегчит вашу работу.