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
@Componentdecorator - 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
- Use meaningful names for @Input and @Output properties
- Keep component communication simple and predictable
- Document complex interactions
- Use TypeScript interfaces for complex data structures
- Handle edge cases and errors in component communication
- Consider using services for complex state management between components
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.