Isaac.

web

Angular Component Communication

Implement patterns for component communication in Angular.

By Emem IsaacMarch 16, 20212 min read
#angular#components#communication#parent child#services
Share:

A Simple Analogy

Component communication is like a phone system. Data flows through channels: parents to children, siblings through services.


Why Communication?

  • Reusable: Components work together
  • Encapsulation: Each component has responsibility
  • Testing: Easier to test isolated components
  • Scalability: Build complex UIs from simple parts
  • Maintainability: Changes isolated to components

Parent to Child (@Input)

// Child component
@Component({
  selector: 'app-card',
  template: `<div>{{ title }}</div>`
})
export class CardComponent {
  @Input() title: string;
}

// Parent component
@Component({
  selector: 'app-parent',
  template: `<app-card [title]="'Hello World'"></app-card>`
})
export class ParentComponent {}

Child to Parent (@Output)

// Child component
@Component({
  selector: 'app-button-group',
  template: `<button (click)="onSelect('save')">Save</button>`
})
export class ButtonGroupComponent {
  @Output() selected = new EventEmitter<string>();
  
  onSelect(action: string) {
    this.selected.emit(action);
  }
}

// Parent component
@Component({
  selector: 'app-dialog',
  template: `<app-button-group (selected)="handleAction($event)"></app-button-group>`
})
export class DialogComponent {
  handleAction(action: string) {
    console.log('Action:', action);
  }
}

Sibling Communication (Service)

// Shared service
@Injectable({ providedIn: 'root' })
export class MessageService {
  private messageSubject = new Subject<string>();
  public message$ = this.messageSubject.asObservable();
  
  sendMessage(msg: string) {
    this.messageSubject.next(msg);
  }
}

// Component A (sender)
@Component({
  selector: 'app-sender'
})
export class SenderComponent {
  constructor(private msgService: MessageService) {}
  
  send() {
    this.msgService.sendMessage('Hello sibling');
  }
}

// Component B (receiver)
@Component({
  selector: 'app-receiver'
})
export class ReceiverComponent implements OnInit {
  constructor(private msgService: MessageService) {}
  
  ngOnInit() {
    this.msgService.message$.subscribe(msg => {
      console.log('Received:', msg);
    });
  }
}

ViewChild Access

@Component({
  selector: 'app-parent',
  template: `<app-child #child></app-child>`
})
export class ParentComponent implements AfterViewInit {
  @ViewChild('child') childComponent: ChildComponent;
  
  ngAfterViewInit() {
    this.childComponent.doSomething();
  }
}

Best Practices

  1. One-way binding: Keep data flow simple
  2. Services: For complex shared state
  3. RxJS: Use observables for multiple updates
  4. Immutability: Don't mutate parent data
  5. Testing: Mock services for unit tests

Related Concepts

  • Change detection
  • Zone management
  • State management (NgRx)
  • Dependency injection

Summary

Communicate between Angular components using @Input/@Output for parent-child, services with RxJS for siblings.

Share:

Written by Emem Isaac

Expert Software Engineer with 15+ years of experience building scalable enterprise applications. Specialized in ASP.NET Core, Azure, Docker, and modern web development. Passionate about sharing knowledge and helping developers grow.

Ready to Build Something Amazing?

Let's discuss your project and explore how my expertise can help you achieve your goals. Free consultation available.

💼 Trusted by 50+ companies worldwide | ⚡ Average response time: 24 hours