Host Elements
In Angular ist das Host Element das DOM-Element, an das eine Komponente gebunden ist. Wenn man eine Komponente wie app-button
im Template verwendet, wird dieses Element zum Host Element der Button-Komponente. Dieses Host Element ist eine Brücke zwischen der Komponente und dem DOM und bietet viele Möglichkeiten zur Interaktion und Manipulation.
Zugriff über ElementRef
Angular erstellt für jede Komponente ein entsprechende DOM-Element, auf das man zugreifen kann.
Wenn man eine Komponente mit einem Component Selector definiert, wird ein DOM-Element mit dem Namen des Selektors erstellt.
import { Component } from '@angular/core';
@Component({
selector: 'app-access-elementref',
imports: [],
templateUrl: './access-elementref.component.html',
styleUrl: './access-elementref.component.scss'
})
export class AccessElementrefComponent {}
Dieser obere Code erzeugt ein DOM-Element <app-access-elementref>
, wie man es auf dem folgenden Screenshot sehen kann.
Würde man ein Component mit einem CSS-Selektor definieren, wie beispielsweise .access-elementref
, kann man <app-access-elementref>
zur Verwendung/Einbindung eines Components nicht mehr verwenden. In diesem Fall würde Angular mitteilen, dass dieses Element nicht bekannt ist.
import { Component } from '@angular/core';
@Component({
selector: '.access-elementref',
imports: [],
templateUrl: './access-elementref.component.html',
styleUrl: './access-elementref.component.scss'
})
export class AccessElementrefComponent {}
In diesem Fall müsste man dann entsprechend auch die Verwendung des Components anpassen und über eine CSS-Klasse realisieren.
<div class="access-elementref"></div>
Mit dieser Verwendung, würde wieder alles korrekt fuktionienren.
Mit Hilfe unterschiedlicher Selektoren hat man am Ende immer ein Element im DOM, das dem entsprechenden Component zugeordnet ist bzw. das dieses Component darstellt/repräsentiert.
Das wir nun wissen, dass es immer ein entsprechendes DOM-Element zu einem Component gibt, können wir auf unterschiedliche Weisen Zugriff auf dieses Element erlangen. Zunächst wird eine Möglichkeit des Zugriffs über ElementRef
gezeigt.
Wir definieren ein Component und binden ElementRef
ein und weisen es eine Variable zu, über die wir dann auf die Eigenschaft nativeElement
zugreifen werden.
import { Component, ElementRef } from '@angular/core';
@Component({
selector: 'app-access-elementref',
imports: [],
templateUrl: './access-elementref.component.html',
styleUrl: './access-elementref.component.scss'
})
export class AccessElementrefComponent {
constructor(
private elementRef: ElementRef
) {
const componentElement = this.elementRef.nativeElement;
console.log('Aktuelles Element', componentElement);
}
}
Irgendwo an einer anderen Stelle in der Applikation wird dieses Component verwendet/eingebunden. Bei der aktuellen Definition gibt eine Standardausgabe access-elementref works!
. Viel interessanter ist der Inhalt der Konsole in Developer Tools.
Hier haben wir folgende Ausgabe.
Diese Methode bietet einen direkten Zugriff auf das native DOM-Element, sollte aber mit Vorsicht verwendet werden, da der direkte DOM-Zugriff die Plattformunabhängigkeit von Angular einschränken kann und bestimmte Sicherheitsrisiken öffnet.
Zugriff mit Renderer2
Diese Methode eignet sich für eine sichere und plattformunabhängige Interatkion mit dem Host Element.
In diesem Element wird ebenfalls ElementRef
verwendet. Allerdings nicht, um direkt auf das DOM-Element, sondern um das Host-Element zuzugreifen.
import { Component, ElementRef, Renderer2 } from '@angular/core';
@Component({
selector: 'app-access-renderer',
imports: [],
template: `<p>Component mit Renderer2</p>`,
styleUrl: './access-renderer.component.scss'
})
export class AccessRendererComponent {
constructor(
private elementRef: ElementRef,
private renderer: Renderer2
) {
this.renderer.setAttribute(
this.elementRef.nativeElement,
'title',
'Beispiel Tooltip'
);
}
}
Mit dem Renderer2
kann man verschiedene Dinge tun. In diesem Beispiel fügen dem Host-Element, also dem Component-Element das Attribute title
mit dem Wert Beispiel Tooltip
hinzu.
Event gesteuerte Aktionen
Man hat auch die Möglichkeit erst bei einem Event etwas mit dem Renderer2
zu tun. Im nächsten Beispiel wird das Beispiel von oben erweitert und ein Button hinzugefügt. Der Klick auf diesen Button führt die Funktion addClass()
aus, welcher den Renderer2
verwendet, um unserem Host Element eine Klasse hinzuzufügen.
import { Component, ElementRef, Renderer2 } from '@angular/core';
@Component({
selector: 'app-access-renderer',
imports: [],
template: `
<p>Component mit Renderer2</p>
<button (click)="addClass()">
Add class
</button>
`,
styleUrl: './access-renderer.component.scss'
})
export class AccessRendererComponent {
constructor(
private elementRef: ElementRef,
private renderer: Renderer2
) {
this.renderer.setAttribute(
this.elementRef.nativeElement,
'title',
'Beispiel Tooltip'
);
}
addClass(): void {
this.renderer.addClass(
this.elementRef.nativeElement,
'new-class'
);
}
}
Host Bindings - Attribute & Eigenschaften
Mit @HostBinding
kann man Eigenschaften des Host Elements (Component Elements) an Eigenschaften (der aktuellen Component-Klasse) binden.
Das folgende Beispiel zeigt eine der einfachsten Verwendungsmöglichkeiten. In diesem Beispiel setzen wir einfach die Hintergrundfarbe für das Component mit HostBinding
auf einen bestimmten Wert.
import { Component, HostBinding } from '@angular/core';
@Component({
selector: 'app-hostbinding-props',
imports: [],
template: `
<p>Ein Platzhalter-Text</p>
`,
styleUrl: './hostbinding-props.component.scss'
})
export class HostbindingPropsComponent {
@HostBinding('style.backgroundColor') styleBgColor = 'lightblue';
}
Wenn wir es bei dieser Konfiguration belassen, wird dieses style
Attribut tatsächlich dem Host Element (Component Element) hinzufügen, hat allerdings keine Auswirkung.
So würde das Ergebnis im Browser aussehen.
GRUND
Ein Host Element in Angular benötigt eine Größen oder Display-Angabe, damit die Stille auch wirklich anwendet.
Wir erweitern unser Beispiel und ergänzen die Stile. Das tun wir ebenfalls mit @HostBinding
und fügen diesmal eine Klasse hinzu.
import { Component, HostBinding } from '@angular/core';
@Component({
selector: 'app-hostbinding-props',
imports: [],
template: `
<p>Ein Platzhalter-Text</p>
`,
styleUrl: './hostbinding-props.component.scss'
})
export class HostbindingPropsComponent {
@HostBinding('style.backgroundColor') styleBgColor = 'lightblue';
@HostBinding('style.display') styleDisplay = 'block';
}
Jetzt wird unsere Hintergrundfarbe korrekt auf das Host Element angewendet.
Mit diesem Beispiel wurde gezeigt, dass man u.a. Stile auf ein Host Element mit Hilfe von @HostBinding
anwenden kann.
Was noch gar keine Verwendung hatte, sind die zugewiesenen Variablen wie styleBgColor
und styleDisplay
. Diese Zuweisung wird erst interessant, wenn man diese Variablen für das Ändern der Werte verwendet.
Im nächsten Beispiel wird unserem Component ein Button hinzugefügt, welcher bei Klick eine Funktion aufruft, die, ebenfalls mittels @HostBinding
bzw. der bereits vorhandenen Variable styleBgColor
den Wert der Hintergrundfarbe auf transparent
ändert.
import { Component, HostBinding } from '@angular/core';
@Component({
selector: 'app-hostbinding-props',
imports: [],
template: `
<p>Ein Platzhalter-Text</p>
<button (click)="changeBg()">
Hintergrund ändern
</button>
`,
styleUrl: './hostbinding-props.component.scss'
})
export class HostbindingPropsComponent {
@HostBinding('style.backgroundColor') styleBgColor = 'lightblue';
@HostBinding('style.display') styleDisplay = 'block';
changeBg(): void {
this.styleBgColor = 'transparent';
}
}
Sobald man nun auf den Button klickt, wird der Hintergrund unseren gesamten Host Elements (Components) von lightblue
auf transparent
geändert.
Wichtiger Hinweis
In diesen Beispielen wurde eine Bindung an ein Attribut ausgeführt. Das erkennt man an dem Punkt .
, welcher den das Attribut und den Wert verbindet.
In diesem Fall: style
ist das Attribut und backgroundColor
ist der Name der Attributs-Eigenschaft.
Auf Events reagieren
Mit @HostBinding
kann man auf verschiedene Events reagieren und diese an bestimmte Funktionen binden, um einen Code-Abschnitt auszuführen.
Im folgenden Beispiel wird ein einfaches Klick-Event auf das Host Element (Component) gelegt und bei jedem Klick die Variable counter
um 1 erhöht.
Damit man die Fläche des Components (Host Elements) besser sieht, wurden ein paar CSS-Stile, ebenfalls per @HostBinding
, hinzugefügt. Diese könnte man auch über die dazugehörige SCSS-Datei hinzufügen können.
import { Component, HostBinding, HostListener } from '@angular/core';
@Component({
selector: 'app-hostbinding-dynamic',
imports: [],
template: `
<div>Counter: {{ counter }}</div>
`,
styleUrl: './hostbinding-dynamic.component.scss'
})
export class HostbindingDynamicComponent {
counter = 0;
@HostBinding('style.padding') componentPadding = '20px';
@HostBinding('style.boxSizing') componentBoxSizing = 'border-box';
@HostBinding('style.backgroundColor') componentBgColor = 'lightblue';
@HostBinding('style.display') componentDisplay = 'block';
@HostListener('click')
onClick(): void {
this.counter++;
}
}
@HostListener
für Events
Während man mit @HostBinding
Eigenschaften und Attribute an Eigenschaften und Methoden des Components binden kann, kann man mit @HostListener
verschiedene Event-Listener an das Component Element (Host Element) binden.
Das folgende Beispiel zeit eine einfach Implementierung eines Maus-Trackers, welche die Werte nur dann aktualisiert, wenn die Maus sich über der Fläche des Components bewegt. Dies ist der Fall, weil (in diesem Fall) nur dort ein Event-Listener dafür registriert wurde.
Damit man eine visuelle Fläche hat, wurden ein paar Stile hinzufügt. Diesmal in der SCSS-Datei.
:host {
display: inline-flex;
justify-content: center;
align-items: center;
width: 600px;
height: 400px;
background-color: lightblue;
}
In unserer Component-Klasse wird nun @HostListener
verwendet. Wir binden das Event mousemove
an unser Component.
import { Component, HostListener } from '@angular/core';
@Component({
selector: 'app-hostbinding-mousetracker',
imports: [],
templateUrl: './hostbinding-mousetracker.component.html',
styleUrl: './hostbinding-mousetracker.component.scss'
})
export class HostbindingMousetrackerComponent {
x = 0;
y = 0;
@HostListener('mousemove', ['$event'])
onMouseMove(event: MouseEvent): void {
this.x = event.clientX;
this.y = event.clientY;
}
}
Globale Events mit @HostListener
Man hat auch die Möglichkeit globale Events mit @HostListener
zu definieren auf diese entsprechend zu reagieren.
Im nächsten Beispiel wird ein Component definiert, welches die zuletzt gedrückte Taste ausgibt.
import { Component, HostListener } from '@angular/core';
@Component({
selector: 'app-hostbinding-globalevents',
imports: [],
template: `
<p>Letzte Taste: {{ lastPressedKey }}
`,
styleUrl: './hostbinding-globalevents.component.scss'
})
export class HostbindingGlobaleventsComponent {
lastPressedKey = '';
@HostListener('window:keydown', ['$event'])
onKeyDown(event: KeyboardEvent): void {
if (event.code === 'Space') {
this.lastPressedKey = 'Leertaste';
} else {
this.lastPressedKey = event.key;
}
}
}
Verwendung der host
Eigenschaft
Kann alternativ auch die host
Eigenschaft im Component Dekorator verwenden, um Stile, Attribute oder Events einem Host Element (Component) hinzuzufügen.
import { Component } from '@angular/core';
@Component({
selector: 'app-host-property',
standalone: true,
template: `<p>host Eigenschaft</p>`,
host: {
'class': 'custom_class',
'[class.active]': 'isActive',
'(click)': 'onClick()',
'[attr.title]': '"My Custom title"',
'[style.display]': '"block"',
'[style.backgroundColor]': '"lightblue"'
}
})
export class HostPropertyComponent {
isActive = true;
onClick(): void {
console.log('Click on component done');
}
}
Als Ergebnis hat man ein Component, ausgestattet mit Attributen, Stilen und Event-Listenern, wie wenn man @HostBinding
und @HostListener
innerhalb der Component-Klasse verwenden würde.