Home > Blockchain >  How to transfer data between components?
How to transfer data between components?

Time:04-16

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

  • Related