How to Create Angular Component
How to Create Angular Component Angular is one of the most powerful and widely adopted front-end frameworks for building dynamic, scalable web applications. At the heart of Angular’s architecture lies the concept of components — reusable, self-contained units that manage a specific part of the user interface. Understanding how to create Angular components is not just a technical skill; it’s the fo
How to Create Angular Component
Angular is one of the most powerful and widely adopted front-end frameworks for building dynamic, scalable web applications. At the heart of Angulars architecture lies the concept of components reusable, self-contained units that manage a specific part of the user interface. Understanding how to create Angular components is not just a technical skill; its the foundation for building maintainable, modular, and high-performance applications.
Whether youre a beginner taking your first steps into Angular or an experienced developer looking to refine your component architecture, mastering component creation is essential. Components enable separation of concerns, promote code reusability, and simplify testing and debugging. In this comprehensive guide, well walk you through every step of creating Angular components from initial setup to advanced best practices with real-world examples and practical tools to accelerate your development workflow.
Step-by-Step Guide
Prerequisites: Setting Up Your Angular Environment
Before creating your first Angular component, ensure your development environment is properly configured. Angular requires Node.js and the Angular CLI (Command Line Interface) to be installed on your machine.
First, verify if Node.js is installed by running the following command in your terminal:
node -v
If Node.js is not installed, download the latest LTS version from nodejs.org and follow the installation instructions.
Next, install the Angular CLI globally using npm (Node Package Manager):
npm install -g @angular/cli
Once installed, verify the Angular CLI version:
ng version
This confirms that your environment is ready. Now, create a new Angular project by running:
ng new my-angular-app
The CLI will prompt you to choose options such as whether to include Angular Routing and which stylesheet format to use (CSS, SCSS, etc.). For beginners, accepting the defaults is recommended.
After the project is generated, navigate into the project folder:
cd my-angular-app
And start the development server:
ng serve
Open your browser and visit http://localhost:4200. You should see the default Angular welcome page, confirming your project is running correctly.
Understanding the Component Structure
An Angular component consists of four core files:
- Component Class (TypeScript) Defines the components logic, properties, and methods.
- Template (HTML) Defines the components view or UI structure.
- Style (CSS/SCSS) Defines the visual styling of the component.
- Metadata (Decorator) Uses the @Component decorator to link the class with the template and styles.
These files are typically grouped together in a single directory to maintain modularity and clarity.
Generating a Component Using the Angular CLI
The fastest and most reliable way to create a component is using the Angular CLI. Run the following command:
ng generate component my-first-component
Or use the shorthand:
ng g c my-first-component
The CLI will automatically create a new folder named my-first-component inside the src/app directory, containing:
my-first-component.component.tsThe component class file.my-first-component.component.htmlThe template file.my-first-component.component.cssThe style file (or .scss if you chose SCSS).my-first-component.component.spec.tsA unit test file (optional but recommended).
Additionally, the CLI automatically registers the new component in the app.module.ts file (if youre using Angular v14 or earlier). In newer versions (v15+), standalone components are the default, so you may need to manually import and declare the component in your app component.
Manually Creating a Component (Without CLI)
If you prefer to create components manually, follow these steps:
- Create a new folder inside
src/appcalledmy-first-component. - Create the TypeScript file:
my-first-component.component.ts
Add the following code to the TypeScript file:
import { Component } from '@angular/core';
@Component({
selector: 'app-my-first-component',
templateUrl: './my-first-component.component.html',
styleUrls: ['./my-first-component.component.css']
})
export class MyFirstComponentComponent {
title = 'My First Angular Component';
}
Notice the @Component decorator. Its a function that tells Angular how to process the class. The key properties are:
- selector The custom HTML tag used to insert this component into other templates (e.g.,
<app-my-first-component></app-my-first-component>). - templateUrl Path to the HTML template file.
- styleUrls Array of paths to CSS/SCSS files for styling.
Next, create the template file: my-first-component.component.html
<div>
<h2>{{ title }}</h2>
<p>This is a dynamically rendered component.</p>
</div>
Then, create the style file: my-first-component.component.css
div {
padding: 20px;
border: 1px solid
ccc;
border-radius: 8px;
background-color:
f9f9f9;
}
h2 {
color:
333;
}
Finally, to display the component in your application, open app.component.html and add the components selector:
<app-my-first-component></app-my-first-component>
Save all files and refresh your browser. You should now see your custom component rendered on the page.
Using Inline Templates and Styles
Instead of external files, you can define templates and styles directly inside the component class using the template and styles properties.
Modify your component class like this:
import { Component } from '@angular/core';
@Component({
selector: 'app-inline-component',
template:
<div style="padding: 15px; background:
e8f5e8; border: 1px dashed #4caf50;">
<h3>Inline Template Component</h3>
<p>This component uses inline HTML and CSS.</p>
</div>
,
styles: [
h3 {
color:
2e7d32;
font-family: Arial, sans-serif;
}
p {
font-size: 14px;
}
]
})
export class InlineComponentComponent {}
While inline templates are useful for small, simple components, theyre harder to maintain for larger UIs. Use them sparingly and prefer external files for better readability and tooling support.
Component Lifecycle Hooks
Angular components go through a series of lifecycle events. Understanding these hooks allows you to execute code at precise moments in the components existence.
Here are the most commonly used lifecycle hooks:
- ngOnInit() Called after the component is initialized. Ideal for data fetching and setup logic.
- ngOnChanges() Called when input properties change.
- ngDoCheck() Called during every change detection cycle.
- ngAfterViewInit() Called after the components view (and child views) are initialized.
- ngOnDestroy() Called just before Angular destroys the component. Use this to unsubscribe from observables or clean up resources.
Example implementation:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-lifecycle-demo',
template:
<p>Component is active: {{ isActive }}</p>
})
export class LifecycleDemoComponent implements OnInit, OnDestroy {
isActive = true;
private timerSubscription: Subscription | null = null;
ngOnInit() {
console.log('Component initialized');
this.timerSubscription = setInterval(() => {
this.isActive = !this.isActive;
}, 3000);
}
ngOnDestroy() {
console.log('Component destroyed');
if (this.timerSubscription) {
this.timerSubscription.unsubscribe();
}
}
}
Always implement ngOnDestroy() when you subscribe to observables or set up timers to prevent memory leaks.
Best Practices
Follow the Single Responsibility Principle
Each component should have one clear purpose. Avoid creating god components that handle too many responsibilities such as fetching data, managing state, rendering UI, and handling user interactions all in one place.
Instead, break down complex interfaces into smaller, focused components. For example:
UserCardComponentDisplays a users profile information.UserListComponentRenders a list ofUserCardComponentinstances.UserSearchComponentHandles search input and filters the list.
This modular approach improves testability, reusability, and maintainability.
Use Input and Output Properties for Communication
Components should communicate through well-defined interfaces: @Input() and @Output().
Input allows parent components to pass data to child components:
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-user-card',
template:
<div class="card">
<h4>{{ userName }}</h4>
<p>Email: {{ userEmail }}</p>
</div>
})
export class UserCardComponent {
@Input() userName: string = '';
@Input() userEmail: string = '';
}
Parent component usage:
<app-user-card [userName]="'John Doe'" [userEmail]="'john@example.com'"></app-user-card>
Output allows child components to emit events to parents:
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-delete-button',
template:
<button (click)="onDelete()" class="btn-danger">Delete</button>
})
export class DeleteButtonComponent {
@Output() deleteEvent = new EventEmitter<string>();
onDelete() {
this.deleteEvent.emit('user-123');
}
}
Parent listens to the event:
<app-delete-button (deleteEvent)="handleDelete($event)"></app-delete-button>
And in the parent component class:
handleDelete(userId: string) {
console.log('Delete request for:', userId);
// Perform delete logic here
}
This pattern ensures loose coupling between components and promotes predictable data flow.
Use Angulars Change Detection Strategy
By default, Angular uses the Default change detection strategy, which checks all components on every event. For performance-critical applications, consider switching to OnPush.
Enable OnPush in your component decorator:
@Component({
selector: 'app-product-item',
templateUrl: './product-item.component.html',
styleUrls: ['./product-item.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProductItemComponent { ... }
With OnPush, Angular only checks for changes when:
- An input reference changes (new object/array).
- An event is triggered within the component (e.g., click, input).
- Explicitly triggered via
ChangeDetectorRef.markForCheck().
This significantly improves performance in large component trees with frequent updates.
Organize Components in Feature Modules
As your application grows, avoid putting all components in the root app module. Instead, group related components, services, and pipes into feature modules.
Example: Create a user feature module:
ng generate module user --route user --module app.module
This creates a user.module.ts and registers routing. Move your user-related components into the user folder and declare them in the module:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UserListComponent } from './user-list/user-list.component';
import { UserDetailComponent } from './user-detail/user-detail.component';
@NgModule({
declarations: [
UserListComponent,
UserDetailComponent
],
imports: [
CommonModule
],
exports: [
UserListComponent,
UserDetailComponent
]
})
export class UserModule { }
Then import UserModule into your main app module or lazy-load it for better performance.
Use Component Interfaces for Type Safety
Define TypeScript interfaces for your component inputs to ensure type safety and improve code documentation:
export interface User {
id: number;
name: string;
email: string;
avatar?: string;
}
@Component({
selector: 'app-user-card',
templateUrl: './user-card.component.html'
})
export class UserCardComponent {
@Input() user: User | null = null;
}
This makes your code more readable and helps catch errors during development.
Keep Templates Clean and Declarative
Templates should focus on structure and presentation. Avoid complex logic inside templates. Use pipes and component methods instead.
Bad:
<div *ngIf="user && user.name.length > 0 && user.email.includes('@')">...</div>
Good:
<div *ngIf="shouldDisplayUser()">...</div>
And in the class:
shouldDisplayUser(): boolean {
return this.user?.name.length > 0 && this.user?.email.includes('@');
}
This improves testability and readability.
Tools and Resources
Angular CLI
The Angular CLI is your primary tool for scaffolding, building, testing, and deploying Angular applications. It automates repetitive tasks and ensures best practices are followed. Key commands:
ng generate componentCreate a new component.ng generate serviceCreate a service.ng generate moduleCreate a feature module.ng serveStart the development server.ng buildBuild for production.ng testRun unit tests.ng lintRun ESLint for code quality.
Angular DevTools Browser Extension
Install the Angular DevTools extension for Chrome or Firefox. It allows you to:
- Inspect component trees and hierarchy.
- View component inputs and outputs.
- Monitor change detection cycles.
- Debug performance issues in real time.
This tool is indispensable for debugging complex component interactions.
VS Code Extensions
Enhance your development experience with these VS Code extensions:
- Angular Language Service Provides IntelliSense, error checking, and navigation in templates.
- Angular Snippets Quick access to common Angular code snippets (e.g.,
ng2for component boilerplate). - ESLint Enforces code quality and style rules.
- Prettier Auto-formats HTML, CSS, and TypeScript files.
Styling Tools
For styling components, consider:
- SCSS/SASS Use nested rules, variables, and mixins for scalable CSS.
- Component-Scoped Styles Angular automatically scopes CSS to components using ViewEncapsulation. Avoid global styles unless necessary.
- Tailwind CSS A utility-first CSS framework that integrates well with Angular for rapid UI development.
Testing Tools
Angular components should be tested using:
- Jasmine Testing framework included by default with Angular CLI.
- Karma Test runner that executes tests in real browsers.
- TestBed Angulars testing utility for configuring and creating components in isolation.
Example test:
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyFirstComponentComponent } from './my-first-component.component';
describe('MyFirstComponentComponent', () => {
let component: MyFirstComponentComponent;
let fixture: ComponentFixture<MyFirstComponentComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MyFirstComponentComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MyFirstComponentComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should display title', () => {
const compiled = fixture.nativeElement;
expect(compiled.querySelector('h2').textContent).toContain('My First Angular Component');
});
});
Documentation and Learning Resources
Official documentation is always the most reliable source:
Supplement with:
- Angular University In-depth video courses.
- YouTube Channels Angular Central, Net Ninja, Traversy Media.
- Stack Overflow For troubleshooting specific issues.
Real Examples
Example 1: Product Card Component
Lets build a reusable product card component for an e-commerce site.
product-card.component.ts
import { Component, Input } from '@angular/core';
export interface Product {
id: number;
name: string;
price: number;
image: string;
inStock: boolean;
}
@Component({
selector: 'app-product-card',
templateUrl: './product-card.component.html',
styleUrls: ['./product-card.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProductCardComponent {
@Input() product: Product | null = null;
get displayPrice(): string {
return this.product ? $${this.product.price.toFixed(2)} : '';
}
get isAvailable(): boolean {
return this.product?.inStock || false;
}
}
product-card.component.html
<div class="product-card" *ngIf="product">
<img [src]="product.image" [alt]="product.name" class="product-image" />
<h3 class="product-name">{{ product.name }}</h3>
<p class="product-price">{{ displayPrice }}</p>
<span class="stock-status" [class.out-of-stock]="!isAvailable">
{{ isAvailable ? 'In Stock' : 'Out of Stock' }}
</span>
</div>
product-card.component.css
.product-card {
border: 1px solid e0e0e0;
border-radius: 8px;
padding: 16px;
text-align: center;
max-width: 200px;
margin: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.product-image {
width: 100%;
height: 120px;
object-fit: cover;
border-radius: 4px;
margin-bottom: 12px;
}
.product-name {
margin: 8px 0;
font-size: 16px;
color:
333;
}
.product-price {
font-weight: bold;
color:
2c3e50;
}
.stock-status {
display: inline-block;
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
margin-top: 8px;
}
.out-of-stock {
background-color:
e74c3c;
color: white;
}
.in-stock {
background-color:
27ae60;
color: white;
}
Usage in parent component:
<app-product-card [product]="product1"></app-product-card>
<app-product-card [product]="product2"></app-product-card>
Example 2: Modal Dialog Component
Reusable modal dialog with dynamic content.
modal.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.css']
})
export class ModalComponent {
@Input() title: string = '';
@Input() content: string = '';
@Output() close = new EventEmitter<void>();
onClose() {
this.close.emit();
}
}
modal.component.html
<div class="modal-overlay" (click)="onClose()">
<div class="modal-content" (click)="$event.stopPropagation()">
<div class="modal-header">
<h3>{{ title }}</h3>
<button class="close-btn" (click)="onClose()">?</button>
</div>
<div class="modal-body">
{{ content }}
</div>
</div>
</div>
modal.component.css
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background: white;
border-radius: 8px;
padding: 20px;
width: 80%;
max-width: 500px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.close-btn {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color:
999;
}
.close-btn:hover {
color:
333;
}
.modal-body {
line-height: 1.6;
color:
555;
}
Parent usage:
<app-modal
*ngIf="showModal"
[title]="'Confirmation'"
[content]="'Are you sure you want to delete this item?'"
(close)="showModal = false">
</app-modal>
FAQs
What is the difference between a component and a directive in Angular?
A component is a directive with a template. All components are directives, but not all directives are components. Components are used to create UI elements with HTML templates and styles, while directives are used to add behavior to existing elements (e.g., *ngIf, *ngFor).
Can I use multiple components in one file?
Technically yes, but its strongly discouraged. Each component should be in its own file for clarity, reusability, and tooling support. The Angular CLI and IDEs expect one component per file.
How do I pass data from a child component to a parent?
Use the @Output() decorator with EventEmitter. The child emits an event, and the parent listens to it using event binding (eventName)="handler()".
What are standalone components?
Introduced in Angular 14, standalone components can be used without being declared in an NgModule. They import dependencies directly via imports in the @Component decorator. This simplifies the architecture and reduces boilerplate.
Why isnt my component rendering?
Common causes:
- Incorrect selector in the template (e.g., using
<my-component>instead of<app-my-component>). - Component not imported or declared in the module (if not standalone).
- Typo in the component class name or file path.
- Missing or incorrect
templateUrlorstyleUrlspaths.
Check the browser console for errors and verify the components selector matches the tag used in the parent template.
How do I test if a component is created properly?
Use Angulars TestBed to create an instance of the component and assert properties and DOM output. Always test inputs, outputs, and rendered content to ensure reliability.
Can I nest components infinitely?
Technically yes, but deep nesting can hurt performance and make the UI hard to debug. Keep nesting shallow (23 levels deep) and use services or state management (like NgRx or Akita) for complex data flows.
Conclusion
Creating Angular components is more than a technical task its a foundational skill that shapes the architecture, performance, and maintainability of your entire application. By following the step-by-step guide outlined above, you now have the knowledge to generate, structure, and optimize components effectively.
Remember that the power of Angular lies in its modularity. Well-designed components promote code reuse, simplify testing, and enable team collaboration. Use the Angular CLI to accelerate development, embrace best practices like OnPush change detection and input/output patterns, and leverage tools like Angular DevTools to debug and optimize your components.
As you continue building applications, challenge yourself to break down complex UIs into smaller, focused components. Refactor aggressively. Document your components clearly. Test rigorously. And always prioritize performance and scalability.
Mastering component creation is the first step toward becoming an expert Angular developer. With consistent practice and adherence to these principles, youll build applications that are not only functional but elegant, efficient, and future-proof.