Datenfluss in Angular: Ein Dialog mit @Input und @Output


Das vorherige Beispiel hat gezeigt, wie sich mit @Input Daten in eine Komponente hineinreichen lassen. In diesem Schritt geht es nun um den umgekehrten Weg: Mit @Output können Informationen aus einer Komponente nach außen gegeben werden. Beispielsweise dann, wenn innerhalb der Komponente ein Ereignis wie das Anklicken eines Buttons auftritt. Die Kombination von @Input und @Output reicht bereits aus, um eine wiederverwendbare Dialogkomponente umzusetzen.
Der folgende Code zeigt den TypeScript-Teil einer solchen Dialogkomponente. Über @Input werden der Titel des Dialogs sowie ein Status übergeben, der steuert, ob der Dialog sichtbar ist oder nicht. Über @Output gibt die Komponente ein Ereignis nach außen weiter, das einen booleschen Wert enthält. Dieses Ereignis wird ausgelöst, sobald im Dialog ein Button angeklickt wurde. In diesem Fall wird die Methode closeDialog aufgerufen.

import {Component, Input, Output, EventEmitter} from '@angular/core';

@Component({
  selector: 'app-dialog',
  standalone: true,
  imports: [],
  templateUrl: './dialog.component.html',
  styleUrl: './dialog.component.scss'
})

export class DialogComponent {

  @Input() title = "";
  @Input() isOpen = false;
  @Output() onClose = new EventEmitter<boolean>();

  closeDialog(): void {
    this.onClose.emit(true);
  }
}

Der HTML-Teil der Komponente bleibt kompakt und klar strukturiert. Der übergebene Titel wird direkt in einer H2-Überschrift dargestellt, während das -Tag als flexibler Platzhalter für beliebige Inhalte dient. Dadurch bleibt der Dialog vollkommen offen für unterschiedliche Anwendungsfälle und schränkt nicht ein, welche Inhalte darin angezeigt werden können.

@if (isOpen) {
  <div class="dialog-overlay">
   <!-- Modal content -->
    <div class="dialog-content">
      <div class="dialog-header">
        <h2>{{title}}</h2>
      </div>
      <div class="dialog-content-box">
        <ng-content></ng-content>
      </div>
      <div class="dialog-footer">
        <span class="span-button" (click)="closeDialog()">Close Dialog</span>
      </div>
    </div>
  </div>
}

Die Steuerung der Dialogsichtbarkeit liegt in der Elternkomponente. Zentral ist dabei eine Variable showDialog, die festlegt, ob der Dialog angezeigt wird oder nicht. Ein Klick auf den Button der Elternkomponente setzt diese Variable auf true, wodurch der Dialog sichtbar wird. Diese Steuerung erfolgt direkt im HTML und erfordert keine zusätzliche TypeScript-Funktion.
Wird hingegen innerhalb der Dialogkomponente – im Beispiel durch ein span-Element – der Button angeklickt, löst dies das Ereignis onClose aus. Dieses Ereignis ist als @Output deklariert und kann in der Elternkomponente ausgewertet werden. Dort wird die Variable showDialog wieder auf false gesetzt, was den Dialog wieder ausblendet.
Der im Dialog dargestellte Text erscheint genau an der Stelle des zuvor definierten -Platzhalters. Statt eines einfachen Textes kann hier ebenso beliebiger HTML-Inhalt eingebunden werden, wodurch der Dialog flexibel einsetzbar bleibt.
Erwähnenswert ist, dass das Ereignis onClose einen booleschen Wert an die Elternkomponente überträgt. Für dieses konkrete Beispiel ist das zwar nicht erforderlich, da der Wert nicht ausgewertet wird. Dennoch zeigt es, dass sich über @Output neben Ereignissen auch Datenstrukturen weiterreichen lassen. Hier genügt jedoch das Auslösen des Ereignisses, um den Dialog auszublenden.

<h1>Dialog Demo</h1>
<button (click)="showDialog = true">Open dialog</button>
<app-dialog title="Demo Dialog Header" [isOpen]="showDialog"
            (onClose)="showDialog = false">
  This is the dialog content.<br>The dialog can be closed by clicking 'Close Dialog' button
</app-dialog>

Die folgende Liste zeigt den TypeScript-Teil der Elternkomponente. Wie bereits erwähnt, fällt die Logik hier sehr überschaubar aus. Wesentlich sind lediglich die Variable zur Steuerung der Sichtbarkeit sowie der Import der Dialogkomponente.

import { Component } from '@angular/core';
import { DialogComponent } from '../dialog/dialog.component';

@Component({
  selector: 'app-dialog-parent',
  standalone: true,
  imports: [DialogComponent],
  templateUrl: './dialog-parent.component.html',
  styleUrl: './dialog-parent.component.scss'
})

export class DialogParentComponent {
  showDialog = false;
}
Stacks Image 235
© 2025 Holger Hinzberg Contact