The Power of Angular @Input and @Output Decorators: A Comprehensive Overview

The Power of Angular @Input and @Output Decorators: A Comprehensive Overview

@Output and @Input Decorators in Angular- Data exchange and communication among angular components.

·

6 min read

Are you working on a codebase in which you use a component you created but need to display data or perform a click function in your child component from the parent component? or perhaps you learned about reusable components and wanted to test them out, but your child or reusable component is having issues talking and communicating with other components? Cheers and congratulations; the purpose of this article is to help you not only comprehend but also solve the problem of communication between components in Angular using Angular's @input and @output decorators.

What is the @input and @output Decorator?

So, first and foremost, let's talk about decorators. Decorators are a way of adding metadata to a class, its properties, or its methods in the context of Angular. Decorators are basically functions that wrap around a class, property, or method and change its behavior in some way.

However, let us briefly discuss class decorators and class field decorators. Class decorators are used to decorate classes, whereas class field decorators are used to decorate class fields or properties.

Class decorators modify the behavior of the entire class. By way of illustration, the @Component() decorator, which is mentioned immediately before a class definition, contains metadata that aids Angular in understanding how the classes or properties should function.

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 title = 'app';
}

Whereas class field decorators modify the behavior of a specific property or field within a class. The best examples are the @Input and @Output decorators.

Now that we've covered that, let's look at the @Input and @Output decorators in particular. These are two of the most common Angular decorators.

@Input Decorator - Parent-to-Child communication

The @Input decorator is used to pass data from one component to another. When the @Input decorator is applied to a property in a child component, it transforms it into a property that can receive data from its parent component. This enables the parent component to communicate with the child component and pass data to it, which can then be used in the template or logic file of the child component.

To have a practical understanding of the above theory, take for example you have two components:

  1. Parent Component

  2. Child Component

The parent component is trying to teach its child how to count numbers, it does this by asking its child to render the number of times a button in its component was clicked. How would this be achieved? Let's take a look at how the parent component HTML would look like below:

parent-component.html file

<button (click)="teachChildNumbersCounting()">Ask Child</button>
<app-child [clickCounts]="clicks"></app-child>

The child component is given the value of clicks in the code above. The child component keeps track of changes in the clickCounts value and updates the child component's count value accordingly. Using interpolation from the child.component.html file, the child component will then show the value of the count in the template.

Wondering what the logic file for the parent component would look like? You can examine the following lines of code below:

parent-component.ts file

export class Component1 { 
  clicks = 0;  
  teachChildNumbersCounting() { 
    this.clicks++; 
  }
}

In the above lines of code, the property clicks is defined and a value of 0 is set to it. Following it is a definition of the teachChildNumbersCounting() function used in parent-component.html, the file that adds +1 to the clicks' value whenever the function is triggered by clicks from the button and then passed to the child component.

However, the child component's clickCounts property is decorated with the @Input decorator in the child-component.ts file so that the child component can render the clicks property through it. The majority of the work is completed here. As was already said, the @Input decorator turns the property clickCounts into a data-receiving property for its parent component. This allows communication between the parent and child components, all thanks to the @Input decorator.

The code implementation for the above explanation on how the @Input decorator is used in the child-component.ts file can be examined in the lines of code below:

child-component.ts file

@Component({
....
}}
export class childComponent {
  @Input() clickCounts: number;
}

With the above implementation, the child component can now render the number of times the parent component clicked the button in its component.html file by making use of interpolation for data binding to display the value set to the clickCounts property.

However, you can examine the code implementation for the explanation made below:

child-component.html file

 <div>
     <p>No of clicks from parent's Component - {{clickCounts}}</p>
</div>

@Output Decorator - Child-to-Parent communication

The @Output decorator, on the other hand, is used to emit events from a child component to a parent component. When the @Output decorator is applied to a property or method in a child component, it transforms it into an event emitter that can be triggered to emit data or events from the child component to its parent component. This enables the child component to communicate with and send data or events back to the parent component.

Nevertheless, keep in mind the example from the section above. Since the child component can now display how many times the button in the parent component was clicked on. Now consider our example in reverse, where the parent component displays the number of times the button in its child component was clicked.

To achieve this, some edits would be made to the child component. First, you can take a look at the child's template component in the following lines of code below:

child-component.html file

  <div>
     <p>No of clicks from parent's Component - {{clickCounts}}</p>
     <button (click)='countClicks()'>Click to count from child</button>
  </div>

The logic file for the above template can be examined below:

child-component.ts file

export class Component2 {
@Output() childToPrentCountClick: EventEmitter<number> = new EventEmitter<number>();
@Input() clickCounts: number;
countClicks() { 
  this.childToPrentCountClick.emit();
  }
}

The event emitter in the component mentioned above is childToPrentCount. This listens to when a click event is triggered. For this to be effective, the parent component would need to be updated. This can be observed in the following lines of code:

parent-component.html file

<button (click)="teachChildNumbersCounting()">Ask Child</button>
<p>No of clicks from child's Component - {{clicks}}</p>
<app-child 
[clickCounts]="clicks" 
childToPrentCountClick="teachChildNumbersCounting()" 
></app-child>

In the above lines of code, the function teachChildNumbersCounting() was passed to the childToParentCountClick event emitter that is decorated with the @Output decorator in the child's decorator. This allows our button clickable with desired logic controlled by the parent component without the child component performing any logic on the button click.

Conclusion

To summarize, during this article, we have discussed how the @Input decorator passes data from a parent component to a child component, whereas the @Output decorator emits events from a child component to a parent component. These decorators, when used together, enable powerful communication and interaction between components in Angular applications.