Components

What is component and how does it work

Components (10 minutes)

Components: The Building Blocks

Components are the fundamental building blocks of Angular applications. Each component consists of:

  • A TypeScript class with the @Component decorator
  • An HTML template defining the UI
  • CSS styles specific to the component

Creating a Component

Checking on Playround: ng-002 | Basic Component

Using Angular CLI:

ng generate component hello-world
# or shorter version
ng g c hello-world

This creates:

hello-world/
├── hello-world.component.ts
├── hello-world.component.html
├── hello-world.component.css
└── hello-world.component.spec.ts

Basic Component Example

// hello-world.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world',
  template: `
    <h1>{{ greeting }}</h1>
    <button (click)="changeGreeting()">Change Greeting</button>
  `,
  styles: [`
    h1 { color: blue; }
  `]
})
export class HelloWorldComponent {
  greeting = 'Hello, World!';

  changeGreeting() {
    this.greeting = 'Hello, Angular!';
  }
}

Component Interaction

Checking on Playround: ng-002 | Parent Component

Parent to Child (@Input)

Use @Input decorator to pass data from parent to child components:

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

@Component({
  selector: 'app-child',
  template: `
    <h2>Hello, {{name}}!</h2>
    <button (click)="onClick()">Click me</button>
  `
})
export class ChildComponent {
  @Input() name: string = '';  // Receive name from parent

  onClick() {
    this.buttonClicked.emit(`Button clicked by ${this.name}`);
  }
}

// parent.component.ts
@Component({
  selector: 'app-parent',
  template: `
    <h1>Parent Component</h1>
    <app-child 
      [name]="parentName"
      (buttonClicked)="handleClick($event)">
    </app-child>
  `
})
export class ParentComponent {
  parentName = 'John';  // Data to send to child

  handleClick(message: string) {
    console.log(message);  // Logs: "Button clicked by John"
  }
}

Child to Parent (@Output)

Use @Output decorator with EventEmitter to send data from child to parent:

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

@Component({
  selector: 'app-child',
  template: `
    <h2>Hello, {{name}}!</h2>
    <button (click)="onClick()">Click me</button>
  `
})
export class ChildComponent {
  @Input() name: string = '';
  @Output() buttonClicked = new EventEmitter<string>();

  onClick() {
    this.buttonClicked.emit(`Button clicked by ${this.name}`);
  }
}

Complete Example

Here’s a practical example combining both @Input and @Output:

// message.interface.ts
interface Message {
  text: string;
  sender: string;
  timestamp: Date;
}

// message.component.ts
@Component({
  selector: 'app-message',
  template: `
    <div class="message">
      <h3>From: {{name}}</h3>
      <input [(ngModel)]="messageText">
      <button (click)="sendMessage()">Send</button>
    </div>
  `
})
export class MessageComponent {
  @Input() name: string = '';
  @Output() messageSent = new EventEmitter<Message>();
  
  messageText = '';

  sendMessage() {
    this.messageSent.emit({
      text: this.messageText,
      sender: this.name,
      timestamp: new Date()
    });
    this.messageText = '';
  }
}

// chat.component.ts
@Component({
  selector: 'app-chat',
  template: `
    <app-message
      [name]="userName"
      (messageSent)="handleMessage($event)">
    </app-message>
    <div class="message-list">
      <div *ngFor="let msg of messages">
        {{msg.sender}}: {{msg.text}}
        <small>{{msg.timestamp | date:'short'}}</small>
      </div>
    </div>
  `
})
export class ChatComponent {
  userName = 'John';
  messages: Message[] = [];

  handleMessage(message: Message) {
    this.messages.push(message);
  }
}

Best Practices

  1. Use meaningful names for @Input and @Output properties
  2. Keep component communication simple and predictable
  3. Document complex interactions
  4. Use TypeScript interfaces for complex data structures
  5. Handle edge cases and errors in component communication
  6. Consider using services for complex state management between components

Last modified March 27, 2025: Edit members.yaml (21070ed)