We use cookies to enhance your experience on the site
CodeWorlds

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}
Go to CodeWorlds