Passing data from parent to child component is trivial in Angular thanks to @Input decorator.

In this post, I want to share how to detect @Input value changes in Angular. This can be useful if you need to perform an action when the value of the input changes.

Using setters and getters

The easiest way to detect value changes is to implement a setter and getter for that property.

When the value of the input changes, the setter will be invoked by Angular.

This is where we can capture the new value. Here is an example:

@Component({
selector: 'child-component',
templateUrl: './child-component.component.html',
styleUrls: ['./child-component.component.css']
})
export class MyComponent {
  private _myInput = '';

  @Input()
  set myInput(value: string) {
   this._myInput = value;
   // Do something with the new value
  }

  get myInput() {
   // Return the current value of the input
   return this._myInput;
  }
}Code language: JavaScript (javascript)

Every time the parent component updates myInput, the setter in child will be called with the new value. Using the setter in the child component, we can update the its state or perform other actions based on the new value. This approach clearly indicates that you are doing something when the input property is set.

That was easy – but what’s the caveat with this approach?

While using a setter makes your code more readable and self-explanatory, it can quickly increase the complexity when there is more than three input properties. In this case, consider using the OnChanges hook.

Using the OnChanges hook

Angular triggers OnChanges lifecycle hook whenever the value of an input parameter changes.

It is possible to access the new and the previous value of the input property within OnChanges. Similar to the previous approach, you can update the component state or manipulate the input value based on your needs.

Start by importing the OnChanges interface in your component:

import { Component, OnChanges } from '@angular/core';Code language: TypeScript (typescript)

Then, decorate your component with the OnChanges interface and implement it as below:

@Component({
selector: 'child-component',
templateUrl: './child-component.component.html',
styleUrls: ['./child-component.component.css']
})
export class ChildComponent implements OnChanges {
   @Input()
   name: string;

   ngOnChanges(changes: SimpleChanges) {
     if (changes.name && changes.name.currentValue) {
       // Do something 
       console.log(changes.name.currentValue);
     }
   }
}
Code language: TypeScript (typescript)

In the ngOnChanges method above, you have access to changes parameter. This parameter contains all properties that changed during the change detection cycle.

It’s common to use the SimpleChanges object to check for changes in specific input properties that you are interested in. This avoids unnecessary processing for properties that haven’t changed.

SimpleChanges type is a hashtable of SimpleChange objects. SimpleChange object contains:

  • previousValue: The previous value of the input
  • currentValue: The current value of the input
  • isFirstChange: Whether this is the first time the input has changed

Best practices when using OnChanges hook

Immutable data

Prefer using immutable data structures for input properties. This makes it easier to detect changes as Angular relies on object references for change detection.

Avoid complex logic

Keep the logic inside ngOnChanges simple and focused. If complex logic is needed, extract it to a separate method or service.

Async operations

Be careful when performing asynchronous operations inside ngOnChanges. Using other lifecycle hooks like ngOnInit or ngAfterViewInit can lead to more expected outcomes for async operations.

Testing

Always write unit tests to ensure that ngOnChanges behaves as expected. You tests can cover different scenarios, including changes to multiple properties and no changes.

Conclusion

In summary, detecting changes in Angular’s @Input() values is essential for building dynamic components. We explored two approaches: using setters and getters for single inputs, and leveraging the OnChanges lifecycle hook for multiple inputs.

Hope you found this useful, see you around!

Umut Esen

Software Engineer specialising in full-stack web application development.

Leave a Reply