DEV Community

Frontend Base
Frontend Base

Posted on

Transitioning to Angular Signal-Based Inputs

With the introduction of Angular v17, the Angular team has brought significant improvements to the framework, focusing on reactivity and type safety. One of the key changes is the shift from the traditional @Input decorator to the new signal-based inputs. This article will guide you through the transition from the old approach to the new, showcasing how to use signal-based inputs effectively in your Angular components.

We'll cover various use cases, such as aliasing, transforming inputs, handling required and optional inputs, and more. By the end of this article, you'll be able to easily adopt these new patterns in your projects.

Common Usage Example

Before

@Component({
  selector: 'app-user-profile',
  template: `<p>User: {{ name }}</p>`
})
export class UserProfileComponent {
  @Input() name: string;
}
Enter fullscreen mode Exit fullscreen mode

After

@Component({
  selector: 'app-user-profile',
  template: `<p>User: {{ name() }}</p>`
})
export class UserProfileComponent {
  name = input<string>();
}
Enter fullscreen mode Exit fullscreen mode

In this simple example, the name input is used to pass a value from the parent component to the UserProfileComponent. The old approach uses the @Input decorator, while the new approach uses the input function, exposing name as a signal that can be accessed by calling name() in the template.


Inputs with Default Value

Before

import { Input } from '@angular/core';

@Component({..})
export class UserProfileComponent {
  @Input() age: number = 30;
}
Enter fullscreen mode Exit fullscreen mode

After

import { input } from '@angular/core';

@Component({..})
export class UserProfileComponent {
  age = input<number>(30);
}
Enter fullscreen mode Exit fullscreen mode

Aliasing an Input

Before

import { Input } from '@angular/core';

@Component({..})
export class UserProfileComponent {
  @Input('userName') name: string = "";
}
Enter fullscreen mode Exit fullscreen mode

After

import { input } from '@angular/core';

@Component({..})
export class UserProfileComponent {
  name = input<string>("", { alias: 'userName' });
}
Enter fullscreen mode Exit fullscreen mode

Transforming an Input

Before

import { booleanAttribute, Input } from '@angular/core';

@Component({..})
export class ToggleComponent {
  @Input({ transform: booleanAttribute }) disabled: boolean = false;
}
Enter fullscreen mode Exit fullscreen mode

After

import { booleanAttribute, input } from '@angular/core';

@Component({..})
export class ToggleComponent {
  disabled = input<boolean>(false, { transform: booleanAttribute });
}
Enter fullscreen mode Exit fullscreen mode

Required Inputs

Before

import { Input } from '@angular/core';

@Component({..})
export class UserProfileComponent {
  @Input({ required: true }) lastName: string;
}
Enter fullscreen mode Exit fullscreen mode

After

import { input } from '@angular/core';

@Component({..})
export class UserProfileComponent {
  lastName = input.required<string>();
}
Enter fullscreen mode Exit fullscreen mode

Monitoring Input Changes

Before

import { Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({..})
export class UserProfileComponent implements OnChange {
  @Input() firstName: string;

  ngOnChanges(changes: SimpleChanges): void {
    console.log(changes);
  }
}
Enter fullscreen mode Exit fullscreen mode

After

import { effect, input } from '@angular/core';

@Component({..})
export class UserProfileComponent {
  firstName = input<string>();

  constructor() {
    effect(() => {
      console.log(this.firstName());
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

As we've explored in this article, transitioning to Angular's signal-based inputs brings a new level of reactivity and type safety to your components. This shift aligns with Angular's ongoing efforts to improve performance and developer experience.

By adopting signal-based inputs, you can:

  1. Simplify your component code
  2. Improved change detection
  3. Enhance reactivity in your applications
  4. Reduce the need for lifecycle hooks like ngOnChanges

While the transition might require some initial effort, especially in larger projects, the benefits in terms of code clarity and maintainability are significant.

Keep exploring, keep learning, and happy coding!

Muhammed from FrontendBase

Top comments (0)