En aquest tema, aprendrem com els components d'Angular poden comunicar-se entre ells. La interacció entre components és essencial per construir aplicacions Angular complexes i ben organitzades. Explorarem diverses tècniques per compartir dades i esdeveniments entre components.

Objectius

  • Entendre com passar dades de components pare a components fill.
  • Aprendre a emetre esdeveniments des de components fill a components pare.
  • Utilitzar serveis per compartir dades entre components no relacionats.

Passar dades de components pare a components fill

@Input Decorator

El decorador @Input permet que un component pare passi dades a un component fill.

Exemple

  1. Component Pare (parent.component.ts)
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <h1>Component Pare</h1>
    <app-child [childMessage]="parentMessage"></app-child>
  `
})
export class ParentComponent {
  parentMessage = "Hola des del component pare!";
}
  1. Component Fill (child.component.ts)
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <h2>Component Fill</h2>
    <p>{{ childMessage }}</p>
  `
})
export class ChildComponent {
  @Input() childMessage: string;
}

Explicació

  • El component pare (ParentComponent) defineix una propietat parentMessage i la passa al component fill (ChildComponent) utilitzant la vinculació de propietats ([childMessage]="parentMessage").
  • El component fill (ChildComponent) rep aquesta dada a través del decorador @Input.

Emetre esdeveniments des de components fill a components pare

@Output Decorator i EventEmitter

El decorador @Output i la classe EventEmitter permeten que un component fill emeti esdeveniments que poden ser escoltats pel component pare.

Exemple

  1. Component Pare (parent.component.ts)
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <h1>Component Pare</h1>
    <app-child (messageEvent)="receiveMessage($event)"></app-child>
    <p>Missatge rebut: {{ message }}</p>
  `
})
export class ParentComponent {
  message: string;

  receiveMessage($event) {
    this.message = $event;
  }
}
  1. Component Fill (child.component.ts)
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <h2>Component Fill</h2>
    <button (click)="sendMessage()">Envia Missatge</button>
  `
})
export class ChildComponent {
  @Output() messageEvent = new EventEmitter<string>();

  sendMessage() {
    this.messageEvent.emit('Hola des del component fill!');
  }
}

Explicació

  • El component fill (ChildComponent) defineix un EventEmitter amb el decorador @Output.
  • Quan es fa clic al botó, el mètode sendMessage emet un esdeveniment amb un missatge.
  • El component pare (ParentComponent) escolta aquest esdeveniment i executa el mètode receiveMessage, que actualitza la propietat message.

Compartir dades entre components no relacionats

Utilitzar Serveis

Els serveis són una manera eficient de compartir dades entre components que no tenen una relació pare-fill.

Exemple

  1. Servei (data.service.ts)
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private messageSource = new BehaviorSubject<string>("Missatge inicial");
  currentMessage = this.messageSource.asObservable();

  changeMessage(message: string) {
    this.messageSource.next(message);
  }
}
  1. Component A (component-a.component.ts)
import { Component } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-component-a',
  template: `
    <h1>Component A</h1>
    <button (click)="newMessage()">Canvia Missatge</button>
  `
})
export class ComponentA {
  constructor(private dataService: DataService) { }

  newMessage() {
    this.dataService.changeMessage("Hola des del Component A!");
  }
}
  1. Component B (component-b.component.ts)
import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-component-b',
  template: `
    <h1>Component B</h1>
    <p>{{ message }}</p>
  `
})
export class ComponentB implements OnInit {
  message: string;

  constructor(private dataService: DataService) { }

  ngOnInit() {
    this.dataService.currentMessage.subscribe(message => this.message = message);
  }
}

Explicació

  • El servei (DataService) utilitza BehaviorSubject per mantenir i emetre l'estat actual del missatge.
  • El ComponentA canvia el missatge cridant al mètode changeMessage del servei.
  • El ComponentB subscriu al currentMessage del servei i actualitza la seva propietat message quan el missatge canvia.

Exercicis Pràctics

Exercici 1: Passar dades de pare a fill

  1. Crea un component pare que tingui una propietat parentData amb el valor "Dades del pare".
  2. Crea un component fill que mostri el valor de parentData passat des del component pare.

Solució

  1. Component Pare
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <h1>Component Pare</h1>
    <app-child [childData]="parentData"></app-child>
  `
})
export class ParentComponent {
  parentData = "Dades del pare";
}
  1. Component Fill
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <h2>Component Fill</h2>
    <p>{{ childData }}</p>
  `
})
export class ChildComponent {
  @Input() childData: string;
}

Exercici 2: Emetre esdeveniments de fill a pare

  1. Crea un component fill que tingui un botó que emeti un esdeveniment amb el missatge "Missatge del fill" quan es fa clic.
  2. Crea un component pare que escolti aquest esdeveniment i mostri el missatge rebut.

Solució

  1. Component Pare
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <h1>Component Pare</h1>
    <app-child (childEvent)="receiveMessage($event)"></app-child>
    <p>Missatge rebut: {{ message }}</p>
  `
})
export class ParentComponent {
  message: string;

  receiveMessage($event) {
    this.message = $event;
  }
}
  1. Component Fill
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <h2>Component Fill</h2>
    <button (click)="sendMessage()">Envia Missatge</button>
  `
})
export class ChildComponent {
  @Output() childEvent = new EventEmitter<string>();

  sendMessage() {
    this.childEvent.emit('Missatge del fill');
  }
}

Resum

En aquesta secció, hem après com els components d'Angular poden comunicar-se entre ells utilitzant @Input per passar dades de pare a fill, @Output i EventEmitter per emetre esdeveniments de fill a pare, i serveis per compartir dades entre components no relacionats. Aquestes tècniques són fonamentals per construir aplicacions Angular modulars i ben organitzades.

Curs d'Angular 2+

Mòdul 1: Introducció a Angular

Mòdul 2: Conceptes bàsics de TypeScript

Mòdul 3: Components i plantilles

Mòdul 4: Directives i pipes

Mòdul 5: Serveis i injecció de dependències

Mòdul 6: Enrutament i navegació

Mòdul 7: Formularis en Angular

Mòdul 8: Client HTTP i observables

Mòdul 9: Gestió d'estat

Mòdul 10: Proves en Angular

Mòdul 11: Temes avançats

Mòdul 12: Desplegament i millors pràctiques

© Copyright 2024. Tots els drets reservats