Angular 16: Required Inputs

This is a smaller feature than the other ones I’ve written about, but one that can save you a lot of time. If you’re unfamiliar with Angular inputs, it’s the basic way you pass data into a component. Let’s see a small example.

import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-button',
  standalone: true,
  imports: [CommonModule],
  template: ` <button>{{ text }}</button> `,
  styleUrls: ['./button.component.scss'],
})
export class ButtonComponent {
  @Input() text: string;
}

Then you can use it like this

<app-button text="My Button"></app-button>

This is a simple enough example, but what happens when your component crashes without the input? You’d have to make sure it’s there before the component can do anything. Let’s see how this would be done before Angular 16.

import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OnInit } from '@angular/core';

@Component({
  selector: 'app-button',
  standalone: true,
  imports: [CommonModule],
  template: ` <button>{{ text }}</button> `,
  styleUrls: ['./button.component.scss'],
})
export class ButtonComponent implements OnInit {
  @Input() text: string;

  ngOnInit(): void {
    if (!this.text) {
      throw new Error('Attribute "text" is required');
    }
  }
}

Now this will fail at runtime when the component doesn’t receive its input. However, this can still lead to components not working at runtime which is when the user is trying to use it. 

Angular’s long-awaited feature to make these required will ensure that if you miss a required input, it’ll fail at compile time. Let’s see how this works.

import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-button',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './button.component.html',
  styleUrls: ['./button.component.scss'],
})
export class ButtonComponent {
  @Input({ required: true }) text: string;
}

Then we use the button incorrectly.

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-root',
  styleUrls: ['./app.component.scss'],
  template: ` <app-button></app-button> `,
})
export class AppComponent {}

If we try to use the component without the input, the app won’t run.

This saves us a bit of time and heartache when dealing with those pesky component inputs.


Previous
Previous

Functional Guards in Angular

Next
Next

Angular 16 Preview: Component Input Bound to Router