All Course > Angular > Angular Material Feb 16, 2025

Angular Reusable Components with @Input & @Output

In the last lesson, we set up Angular Material and used its pre-built UI components like buttons, cards, and dialogs. Now, we’ll take it further by making our own reusable components, which is key for scalable apps.

Why Reusable Components Matter

I once built a dashboard with multiple cards showing user data. Each card had the same layout but different content. Instead of copying code, I made a single reusable component that took data as input. This saved time and kept the code clean.

  • Reusable components help:

  • Reduce duplicate code

  • Make updates easier

  • Improve app performance

Parent-Child Communication with @Input

To pass data from a parent to a child component, we use @Input(). Let’s say we have a UserCard component that displays user details.

Define the Child Component

// user-card.component.ts  
import { Component, Input } from '@angular/core';  

@Component({  
  selector: 'app-user-card',  
  template: `  
    <div class="card">  
      <h3>{{ user.name }}</h3>  
      <p>{{ user.email }}</p>  
    </div>  
  `  
})  
export class UserCardComponent {  
  @Input() user: any; // Data comes from parent  
}  

Pass Data from Parent

// app.component.ts  
@Component({  
  selector: 'app-root',  
  template: `  
    <app-user-card [user]="currentUser"></app-user-card>  
  `  
})  
export class AppComponent {  
  currentUser = { name: 'John Doe', email: '[email protected]' };  
}  

Here, [user] binds data from AppComponent to UserCardComponent.

Child-Parent Communication with @Output

Sometimes, a child needs to send data back to the parent. We use @Output() with events.

Emit an Event from Child

// user-card.component.ts  
import { Component, Input, Output, EventEmitter } from '@angular/core';  

@Component({  
  selector: 'app-user-card',  
  template: `  
    <div class="card">  
      <h3>{{ user.name }}</h3>  
      <button (click)="onSelect()">Select User</button>  
    </div>  
  `  
})  
export class UserCardComponent {  
  @Input() user: any;  
  @Output() userSelected = new EventEmitter<any>();  

  onSelect() {  
    this.userSelected.emit(this.user);  
  }  
}  

Handle Event in Parent

// app.component.ts  
@Component({  
  selector: 'app-root',  
  template: `  
    <app-user-card  
      [user]="currentUser"  
      (userSelected)="handleSelection($event)">  
    </app-user-card>  
  `  
})  
export class AppComponent {  
  currentUser = { name: 'John Doe', email: '[email protected]' };  

  handleSelection(user: any) {  
    console.log('Selected User:', user);  
  }  
}  

Now, clicking the button in the child sends data to the parent.

Dynamic Components for Better Reusability

Sometimes, you need components to load dynamically. For example, a dashboard that shows different widgets based on user choice.

Create a Dynamic Host

// dynamic-host.component.ts  
import { Component, ViewChild, ViewContainerRef } from '@angular/core';  

@Component({  
  selector: 'app-dynamic-host',  
  template: `<ng-container #host></ng-container>`  
})  
export class DynamicHostComponent {  
  @ViewChild('host', { read: ViewContainerRef }) host: ViewContainerRef;  

  loadComponent(component: any) {  
    this.host.clear();  
    this.host.createComponent(component);  
  }  
}  

Use It in Parent

// app.component.ts  
import { UserCardComponent } from './user-card.component';  

@Component({  
  selector: 'app-root',  
  template: `  
    <button (click)="loadUserCard()">Load Card</button>  
    <app-dynamic-host></app-dynamic-host>  
  `  
})  
export class AppComponent {  
  constructor(private resolver: ComponentFactoryResolver) {}  

  loadUserCard() {  
    const factory = this.resolver.resolveComponentFactory(UserCardComponent);  
    this.dynamicHost.loadComponent(factory);  
  }  
}  

Conclusion

  • Use @Input() to pass data into a child component.

  • Use @Output() to send data back to the parent.

  • Dynamic components help build flexible UIs.

Now that you know how to make reusable components, the next lesson will cover optimizing Angular apps for speed.

Comments

There are no comments yet.

Write a comment

You can use the Markdown syntax to format your comment.

Tags: angular typescript