Signal-based Inputs and Outputs (Angular 17+)
Signal Inputs
1import { Component, input } from '@angular/core';
2
3@Component({
4 selector: 'app-samurai-card',
5 standalone: true,
6 template: \`
7 <div class="card">
8 <h2>{{ name() }}</h2>
9 <p>Level: {{ level() }}</p>
10 <p>Clan: {{ clan() }}</p>
11 </div>
12 \`
13})
14export class SamuraiCardComponent {
15 // Optional input with default value
16 name = input('Unknown');
17
18 // Required input
19 level = input.required<number>();
20
21 // Input with transformation
22 clan = input('Ronin', {
23 transform: (value: string) => value.toUpperCase()
24 });
25
26 // Input with alias
27 samuraiId = input(0, { alias: 'id' });
28}
29
30// Usage:
31<app-samurai-card
32 name="Musashi"
33 [level]="10"
34 clan="niten">
35</app-samurai-card>
Model Inputs (Two-way binding)
1import { Component, model } from '@angular/core';
2
3@Component({
4 selector: 'app-health-bar',
5 standalone: true,
6 template: \`
7 <div class="health-bar">
8 <div class="fill" [style.width.%]="health()"></div>
9 <input
10 type="range"
11 [value]="health()"
12 (input)="health.set(+$any($event.target).value)">
13 </div>
14 \`
15})
16export class HealthBarComponent {
17 // Model input - works like [(ngModel)]
18 health = model(100);
19}
20
21// Usage with two-way binding:
22<app-health-bar [(health)]="currentHealth"></app-health-bar>
Signal Queries
1import { viewChild, viewChildren, contentChild, contentChildren } from '@angular/core';
2
3@Component({...})
4export class ParentComponent {
5 // Instead of @ViewChild
6 childComponent = viewChild(ChildComponent);
7 inputElement = viewChild<ElementRef>('myInput');
8
9 // Instead of @ViewChildren
10 allCards = viewChildren(CardComponent);
11
12 // Instead of @ContentChild
13 projectedHeader = contentChild('header');
14}