|

Angular Parent Child Communication

Angular Parent Child Communication

In this tutorial we’ll look at nested components in Angular and how to use them. Why nest components? It helps to organize the layout of the user interface in addition to allowing specific functionality to be packaged up and re used in other components. This means that a nested component is going to need a way to communicate with its parent or containing component. Components can nest several times if you like. You can almost think of multiple boxes with the largest box on the outside, and small boxes contained inside. Since each component is fully encapsulated, Angular makes use of Inputs and Outputs to create communication paths outside of its own boundaries.


Create A Component To Nest

To begin, let’s create a shared directory in the Angular app folder.
angular shared directory

Within this folder we can add the files we will use for the component we’ll build. It will be a thumb component that displays a number of thumbs up icons based on the rating a game has. We’ll need a thumb.component.html, thumb.component.css, and thumb.component.ts file for this.
nested component in shared directory

Generally, a nested component should make use of a template which manages a small part of a larger interface. The component should have a selector defined, so that it can be nested in a containing component. In addition, it will usually have a means to communicate with its parent using @Input() and @Output decorators. For our purpose, we will create a component which displays thumbs and can be nested in the game-list.component.html template. Our structure looks a bit like this.
angular nested component diagram

Within the template for the thumb component, we can start with the following markup. It makes use of font awesome to show thumbs up symbols. In order for the component to display various numbers of thumbs, the parent needs to provide the rating number to the thumb component as an @Input(). Also, we’ll add the ability to raise events in the nested component using @Output() and event emitter.


thumb.component.html

The component will display 5 thumbs, but we can crop the component to display less than 5 thumbs based on the rating a game has. So we can see a couple of property bindings there, so now let’s define the thumb component and its bindings in the associated Typescript file.

The rating property is a number provided by the data in the games array. The thumbWidth is calculated based on the value of the rating. The way this happens is using the ngOnChanges() lifecycle hook.


thumb.component.ts

This CSS styling in the component style sheet will give us the cropping effect we are looking for.


thumb.component.css


Nested Component As Directive

In order to use the nested component, we first need to add it to the declarations of a module.


app.module.ts


game-list.component.html

Now we can dive into the parent component template and add the nested component using it’s selector. Since we have all the plumbing in place, look at how the IDE actually picks up on the new game-thumb component in an intellisense like way.
angular intellisense for components

Note the highlighted line to show where the nested component is referenced.

At this point, the nested component seems to be working. It is not fully functional, as it simply displays 5 thumbs no matter what rating the game has. The reason for this is because ngOnChanges() is not firing since it only watches for changes on Input properties. We have not configured that yet, but will do so next.
angular component as directive example


Parent To Child Communication With @Input

In order for a nested component to receive input from its parent, it can expose a property to do so. This is done using the @Input() Decorator. This decorator can be used to decorate any property in the nested component’s class. In the markup below, we are specifying that we want the rating value passed into the nested component.


thumb.component.ts

Now in the template of the parent component, Property Binding is used to pass data to the nested component. Note the use of square brackets in the highlighted code. The binding source is set to the data that the parent wants to send to the child. So this template is passing the game.thumbRating value to the thumb component.


game-list.component.html

Now the thumbs are dynamic! This is because the thumb component is receiving the correct value for the number of thumbs to display based on the rating.
angular input decorator binding


Communicating From Child To Parent With @Output

In the clip above, we now have communication happening from the parent to the child component. Now we want the ability to go in reverse. For example if something is clicked in the child, we can pass that event up to the parent. This is done by raising an event in combination with the @Output() Decorator and the EventEmitter. In fact, the only way a nested component can pass data to it’s parent is with an Event. The data to pass is the Event Payload.

First off, we can specify that when the thumb component is clicked, the onClick() method will run.


thumb.component.html

Then in the component, we have to define the onClick() method. In addition we set up the ratingClicked as an Event Property by using the @Output() decorator. This property emits an event using the EventEmitter.


thumb.component.ts

Below is the containing component, where we can set up event binding. We bind to the event raised from the thumb component using event binding denoted by (ratingClicked)=’onRatingClicked($event)’. This means we are listening for the ratingClicked event raised from the thumb component. When that event triggers, we want to run the onRatingClicked() method with $event as the payload. This method will be defined in game-list.component.ts next.


game-list.component.html

Here is the onRatingClicked() method which simply sets the page title to something new based on the payload of the event.


game-list.component.ts

Looking Good!


Summary

Nested Component Key Points

  • A nested component is built following the same steps as any other component you might build in Angular.
  • The @Input() Decorator can be used on a nested component property any time it needs input data from it’s parent or containing component.
  • Any type of property can be decorated with the @Input() Decorator.
  • The @Output Decorator is used to decorate a nested component property for when it needs to raise events to pass back to the parent.
  • Only properties with the type of EventEmitter can be used with the @Output Decorator.
  • Use the generic argument to specify the type of the event payload.
  • Use the new keyword to create an instance of the EventEmitter.

Containing Component Key Points

  • In the containing component template, use the nested component as a directive.
  • The name of the directive is based on the selector property.
  • Use Property Binding to pass data to the nested component.
  • A Property decorated with the @Input() decorator on the nested component can be used as a binding target.
  • Use Event Binding to respond to events raised from the nested component.
  • A Property decorated with the @Output() decorator on the nested component can be used as a binding target.
  • To access the event payload, you can use the $event variable passed from the nested component.
|