I need your help. I have 2 components: header
and sidena
. I use the material-UI
library. In the sidenav component, I try to create an opened variable that is responsible for opening the sidenav
and use EventEmmiter
to pass it to the header
component, but I get an error in sidenav.component.html
:
Type EventEmitter<boolean> is not assignable to type boolean
I have 2 questions: how do I pass a variable in the header component to open sidenav and do I understand correctly that the .emit
method provides a certain type to our eventEmmiter
? Thank you very much
sidenav.component.ts
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
@Component({
selector: 'app-sidena',
templateUrl: './sidena.component.html',
styleUrls: ['./sidena.component.css']
})
export class SidenaComponent implements OnInit {
@Output() opened = new EventEmitter<boolean>()
ngOnInit(): void {
this.opened.emit(false);
}
}
sidenav.component.html
<mat-sidenav-container>
<mat-sidenav mode="side" [(opened)]="opened">
Sidenav
</mat-sidenav>
</mat-sidenav-container>
header.component.ts
import {Component, HostListener, Input, OnInit} from '@angular/core';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
@Input() opened
ngOnInit(): void {}
}
header.component.html
<header>
<button (click)="opened=!opened">Toggle Opened</button>
<app-sidena></app-sidena>
</header>
CodePudding user response:
Right now you are trying to use two-way data binding in your SidenaComponent in html:
<mat-sidenav-container>
<mat-sidenav mode="side" [(opened)]="opened">
Sidenav
</mat-sidenav>
</mat-sidenav-container>
but it should be
<mat-sidenav-container>
<mat-sidenav mode="side" (opened)="open($event)">
Sidenav
</mat-sidenav>
</mat-sidenav-container>
then in typescript of SidenaComponent you should correctly react to opened event like that:
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
@Component({
selector: 'app-sidena',
templateUrl: './sidena.component.html',
styleUrls: ['./sidena.component.css']
})
export class SidenaComponent implements OnInit {
@Output() opened = new EventEmitter<boolean>()
open(event): void {
this.opened.emit(event);
}
}
this way you get correct value from opened event of Material component. Next step is sending this value up, to your parrent component: HeaderComponent. And you should do it like this:
<header>
<button (click)="opened=!opened">Toggle Opened</button>
<app-sidena (opened)="isOpened($event)"></app-sidena>
</header>
And in typescript:
import {Component, HostListener, Input, OnInit} from '@angular/core';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
private opened: boolean;
isOpened(event): void {
this.opened = event;
}
}
This way you have state of side menu in your header component.
Also if you need to pass value down to SidenaComponent from HeaderComponent just use @Input and pass it down.
CodePudding user response:
An other way is to use a service in which you store variables. You can then access those variables in every other components.
To generate this service:
ng generate service yourService
For more infos, here's the official documentation: https://angular.io/tutorial/toh-pt4