🎯 Ejemplos recomendados
Balanced sample collections from various categories for you to explore
Ejemplos de Framework Angular
Ejemplos esenciales de Angular para desarrollo web empresarial con TypeScript, componentes y módulos
💻 Hola Mundo en Angular typescript
🟢 simple
⭐⭐
Componentes básicos de Angular, TypeScript y conceptos fundamentales
⏱️ 30 min
🏷️ angular, typescript, components, di
Prerequisites:
TypeScript, Basic Angular concepts, Object-oriented programming
// Angular Hello World Examples
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="app-container">
<h1>{{ title }}</h1>
<p>{{ description }}</p>
<button (click)="updateMessage()">Update Message</button>
<p>Click count: {{ clickCount }}</p>
</div>
`,
styles: [`
.app-container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
text-align: center;
font-family: Arial, sans-serif;
}
h1 {
color: #3f51b5;
}
button {
margin: 10px;
padding: 10px 20px;
background-color: #3f51b5;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #303f9f;
}
`]
})
export class AppComponent {
title = 'Hello, Angular!';
description = 'Welcome to Angular framework';
clickCount = 0;
updateMessage() {
this.clickCount++;
this.title = `Clicked ${this.clickCount} times!`;
}
}
// 2. Component with Inputs and Outputs
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-greeting',
template: `
<div class="greeting">
<h2>{{ greeting }}, {{ name }}!</h2>
<p>{{ message }}</p>
<button (click)="sayHello()">Say Hello</button>
</div>
`,
styles: [`
.greeting {
padding: 15px;
border: 1px solid #ddd;
border-radius: 8px;
margin: 10px 0;
}
`]
})
export class GreetingComponent {
@Input() name: string = 'World';
@Input() message: string = 'Welcome to Angular';
@Output() hello = new EventEmitter<string>();
sayHello() {
this.hello.emit(`Hello from ${this.name}!`);
}
}
// Usage in parent component:
// <app-greeting [name]="userName" [message]="customMessage" (hello)="handleHello($event)"></app-greeting>
// 3. Service Example
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DataService {
private items: any[] = [];
getItems() {
return this.items;
}
addItem(item: any) {
this.items.push(item);
}
removeItem(index: number) {
this.items.splice(index, 1);
}
updateItem(index: number, item: any) {
this.items[index] = item;
}
}
// 4. Component with Dependency Injection
import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';
@Component({
selector: 'app-item-list',
template: `
<div class="item-list">
<h3>{{ title }}</h3>
<ul>
<li *ngFor="let item of items; let i = index">
{{ item.name }}
<button (click)="removeItem(i)">Remove</button>
<button (click)="editItem(i)">Edit</button>
</li>
</ul>
<div>
<input #newItem type="text" placeholder="Add new item">
<button (click)="addItem(newItem.value)">Add</button>
</div>
</div>
`,
styles: [`
.item-list {
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
}
ul {
list-style: none;
padding: 0;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px;
border-bottom: 1px solid #eee;
}
li button {
margin-left: 10px;
}
div {
margin-top: 10px;
display: flex;
gap: 10px;
}
div input {
flex: 1;
padding: 5px;
}
`]
})
export class ItemListComponent implements OnInit {
@Input() title: string = 'Items';
items: any[] = [];
constructor(private dataService: DataService) {}
ngOnInit() {
this.items = this.dataService.getItems();
}
addItem(itemName: string) {
if (itemName.trim()) {
this.dataService.addItem({
name: itemName.trim(),
createdAt: new Date()
});
this.items = this.dataService.getItems();
}
}
removeItem(index: number) {
this.dataService.removeItem(index);
this.items = this.dataService.getItems();
}
editItem(index: number) {
const newName = prompt('Edit item name:', this.items[index].name);
if (newName && newName.trim()) {
this.dataService.updateItem(index, {
...this.items[index],
name: newName.trim(),
updatedAt: new Date()
});
this.items = this.dataService.getItems();
}
}
}
💻 Patrones Avanzados de Angular typescript
🟡 intermediate
⭐⭐⭐⭐
Patrones avanzados de Angular incluyendo RxJS, formularios, routing y servicios HTTP
⏱️ 35 min
🏷️ angular, typescript, forms, http, rxjs
Prerequisites:
Angular basics, TypeScript, RxJS concepts, HTTP client
// Angular Advanced Patterns
// 1. Reactive Forms with FormBuilder
import { Component, OnInit, FormGroup, FormBuilder, Validators } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'app-user-form',
template: `
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="name">Name:</label>
<input id="name" formControlName="name" type="text">
<div *ngIf="userForm.get('name').invalid && userForm.get('name').touched"
class="error">
Name is required and must be at least 2 characters
</div>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input id="email" formControlName="email" type="email">
<div *ngIf="userForm.get('email').invalid && userForm.get('email').touched"
class="error">
Please enter a valid email address
</div>
</div>
<div class="form-group">
<label for="age">Age:</label>
<input id="age" formControlName="age" type="number">
<div *ngIf="userForm.get('age').invalid && userForm.get('age').touched"
class="error">
Age must be between 18 and 120
</div>
</div>
<div class="form-actions">
<button type="submit" [disabled]="!userForm.valid">Submit</button>
<button type="button" (click)="resetForm()">Reset</button>
</div>
</form>
<div *ngIf="submittedData" class="submitted-data">
<h3>Submitted Data:</h3>
<pre>{{ submittedData | json }}</pre>
</div>
`,
styles: [`
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
input.ng-invalid.ng-touched {
border-color: #f44336;
}
.error {
color: #f44336;
font-size: 12px;
margin-top: 5px;
}
.form-actions {
margin-top: 20px;
}
.form-actions button {
margin-right: 10px;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
button[type="submit"]:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.submitted-data {
margin-top: 20px;
padding: 15px;
background-color: #f8f9fa;
border-radius: 4px;
}
`]
})
export class UserFormComponent implements OnInit {
userForm: FormGroup;
submittedData: any = null;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.userForm = this.fb.group({
name: ['', [Validators.required, Validators.minLength(2)]],
email: ['', [Validators.required, Validators.email]],
age: [18, [Validators.required, Validators.min(18), Validators.max(120)]]
});
}
onSubmit() {
if (this.userForm.valid) {
this.submittedData = this.userForm.value;
console.log('Form submitted:', this.submittedData);
}
}
resetForm() {
this.userForm.reset();
this.submittedData = null;
}
}
// 2. HTTP Service with RxJS
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, catchError, tap } from 'rxjs/operators';
import { of } from 'rxjs';
export interface User {
id: number;
name: string;
email: string;
age: number;
}
@Injectable({
providedIn: 'root'
})
export class UserService {
private apiUrl = 'https://jsonplaceholder.typicode.com/users';
constructor(private http: HttpClient) {}
getUsers(): Observable<User[]> {
return this.http.get<User[]>(this.apiUrl).pipe(
catchError(this.handleError('getUsers', []))
);
}
getUser(id: number): Observable<User> {
return this.http.get<User>(`${this.apiUrl}/${id}`).pipe(
catchError(this.handleError(`getUser id=${id}`, null))
);
}
createUser(user: Partial<User>): Observable<User> {
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
return this.http.post<User>(this.apiUrl, user, { headers }).pipe(
catchError(this.handleError('createUser', null))
);
}
updateUser(id: number, user: Partial<User>): Observable<User> {
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
return this.http.put<User>(`${this.apiUrl}/${id}`, user, { headers }).pipe(
catchError(this.handleError(`updateUser id=${id}`, null))
);
}
deleteUser(id: number): Observable<void> {
return this.http.delete<void>(`${this.apiUrl}/${id}`).pipe(
catchError(this.handleError(`deleteUser id=${id}`, of(void 0)))
);
}
private handleError<T>(operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
console.error(`${operation} failed: ${error.message}`);
return of(result as T);
};
}
}
// 3. Component with HTTP Service
import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app-user-list',
template: `
<div class="user-list">
<h2>User Management</h2>
<div class="user-actions">
<button (click)="loadUsers()">Load Users</button>
<button (click)="showAddForm = true" [disabled]="loading">Add User</button>
</div>
<div *ngIf="loading" class="loading">Loading users...</div>
<div *ngIf="error" class="error">{{ error }}</div>
<table *ngIf="users.length > 0">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Age</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users; let i = index">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.age }}</td>
<td>
<button (click)="editUser(user)" class="edit-btn">Edit</button>
<button (click)="deleteUser(user.id)" class="delete-btn">Delete</button>
</td>
</tr>
</tbody>
</table>
<!-- Add/Edit User Modal -->
<div *ngIf="showAddForm || editingUser" class="modal">
<div class="modal-content">
<h3>{{ editingUser ? 'Edit User' : 'Add New User' }}</h3>
<form (ngSubmit)="saveUser()">
<div class="form-group">
<label>Name:</label>
<input [(ngModel)]="formData.name" type="text" required>
</div>
<div class="form-group">
<label>Email:</label>
<input [(ngModel)]="formData.email" type="email" required>
</div>
<div class="form-group">
<label>Age:</label>
<input [(ngModel)]="formData.age" type="number" required>
</div>
<div class="form-actions">
<button type="submit">{{ editingUser ? 'Update' : 'Create' }}</button>
<button type="button" (click)="cancelEdit()">Cancel</button>
</div>
</form>
</div>
</div>
</div>
`,
styles: [`
.user-list {
padding: 20px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #f5f5f5;
font-weight: bold;
}
.user-actions {
margin-bottom: 20px;
}
.user-actions button {
margin-right: 10px;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
}
.modal-content {
background: white;
padding: 30px;
border-radius: 8px;
max-width: 500px;
width: 90%;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
.form-actions {
margin-top: 20px;
text-align: right;
}
.form-actions button {
margin-left: 10px;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
}
`]
})
export class UserListComponent implements OnInit {
users: User[] = [];
loading = false;
error = '';
showAddForm = false;
editingUser: User | null = null;
formData = {
name: '',
email: '',
age: 0
};
constructor(private userService: UserService) {}
ngOnInit() {
this.loadUsers();
}
loadUsers() {
this.loading = true;
this.userService.getUsers().subscribe({
next: (users) => {
this.users = users;
this.loading = false;
},
error: (error) => {
this.error = 'Failed to load users';
this.loading = false;
}
});
}
saveUser() {
if (this.editingUser) {
this.userService.updateUser(this.editingUser.id, this.formData).subscribe({
next: (updatedUser) => {
const index = this.users.findIndex(u => u.id === updatedUser.id);
if (index !== -1) {
this.users[index] = updatedUser;
}
this.cancelEdit();
},
error: (error) => {
this.error = 'Failed to update user';
}
});
} else {
this.userService.createUser(this.formData).subscribe({
next: (newUser) => {
this.users.push(newUser);
this.cancelEdit();
},
error: (error) => {
this.error = 'Failed to create user';
}
});
}
}
editUser(user: User) {
this.editingUser = user;
this.showAddForm = true;
this.formData = { ...user };
}
deleteUser(id: number) {
if (confirm('Are you sure you want to delete this user?')) {
this.userService.deleteUser(id).subscribe({
next: () => {
this.users = this.users.filter(u => u.id !== id);
},
error: (error) => {
this.error = 'Failed to delete user';
}
});
}
}
cancelEdit() {
this.showAddForm = false;
this.editingUser = null;
this.formData = {
name: '',
email: '',
age: 0
};
}
}
// Main App Component
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="app">
<header>
<h1>Angular Advanced Examples</h1>
<nav>
<a routerLink="/">Home</a>
<a routerLink="/users">Users</a>
</nav>
</header>
<main>
<app-hello-world></app-hello-world>
<app-greeting name="Angular" message="Welcome to advanced patterns!"></app-greeting>
<app-item-list title="Todo List"></app-item-list>
<app-user-form></app-user-form>
<app-user-list></app-user-list>
</main>
</div>
`,
styles: [`
.app {
min-height: 100vh;
font-family: Arial, sans-serif;
}
header {
background-color: #3f51b5;
color: white;
padding: 1rem;
text-align: center;
}
header h1 {
margin: 0;
}
nav {
margin-top: 1rem;
}
nav a {
color: white;
text-decoration: none;
margin: 0 1rem;
padding: 0.5rem 1rem;
border-radius: 4px;
transition: background-color 0.3s;
}
nav a:hover {
background-color: rgba(255, 255, 255, 0.1);
}
nav a.router-link-active {
background-color: rgba(255, 255, 255, 0.2);
}
main {
padding: 2rem;
max-width: 1200px;
margin: 0 auto;
}
`]
})
export class AppComponent {}
💻 Patrones Empresariales de Angular typescript
🔴 complex
⭐⭐⭐⭐⭐
Patrones empresariales de Angular incluyendo lazy loading, guards, interceptors y pruebas
⏱️ 50 min
🏷️ angular, enterprise, testing, architecture, patterns
Prerequisites:
Advanced Angular, TypeScript, Testing frameworks, Enterprise patterns
// Angular Enterprise Patterns
// 1. Lazy Loading Modules
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'users', loadChildren: () => import('./users/users.module').then(m => m.UsersModule) },
{ path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule), canActivate: [AdminGuard] },
{ path: '**', redirectTo: '' }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
// 2. Route Guards
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AdminGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(): boolean {
if (this.authService.isAdmin()) {
return true;
}
this.router.navigate(['/login']);
return false;
}
}
// 3. HTTP Interceptor
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
import { AuthService } from './auth.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) {}
intercept(req: HttpRequest, next: HttpHandler) {
const authToken = this.authService.getToken();
if (authToken) {
req = req.clone({
headers: req.headers.set('Authorization', `Bearer ${authToken}`)
});
}
return next.handle(req);
}
}
// 4. Error Handling Service
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
export interface ApiError {
message: string;
status: number;
statusText: string;
details: any;
}
@Injectable({
providedIn: 'root'
})
export class ErrorHandlingService {
constructor(private http: HttpClient) {}
handleError(error: HttpErrorResponse): Observable<never> {
let errorMessage = 'An unknown error occurred';
if (error.error instanceof ErrorEvent) {
errorMessage = `Error: ${error.error.message}`;
} else {
errorMessage = `Error Code: ${error.status} - ${error.message}`;
}
console.error(errorMessage, error);
return throwError(() => errorMessage);
}
}
// 5. Advanced Component with Lifecycle Hooks
import {
Component,
OnInit,
OnDestroy,
AfterViewInit,
OnChanges,
SimpleChanges
} from '@angular/core';
@Component({
selector: 'app-lifecycle-demo',
template: `
<div class="lifecycle-demo">
<h2>Lifecycle Demo</h2>
<p>Message: {{ message }}</p>
<p>Timestamp: {{ timestamp }}</p>
<p>Component Status: {{ status }}</p>
<button (click)="triggerUpdate()">Manual Update</button>
</div>
`,
styles: [`
.lifecycle-demo {
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
margin: 10px 0;
}
`]
})
export class LifecycleDemoComponent implements OnInit, OnDestroy, AfterViewInit, OnChanges {
message = 'Component initialized';
timestamp = new Date();
status = 'active';
private updateInterval: any;
ngOnInit() {
console.log('Component initialized');
this.startAutoUpdate();
}
ngAfterViewInit() {
console.log('View initialized');
this.status = 'view ready';
}
ngOnChanges(changes: SimpleChanges) {
console.log('Properties changed:', changes);
}
ngOnDestroy() {
console.log('Component destroyed');
this.stopAutoUpdate();
}
triggerUpdate() {
this.message = 'Manual update triggered';
this.timestamp = new Date();
}
private startAutoUpdate() {
this.updateInterval = setInterval(() => {
this.timestamp = new Date();
}, 5000);
}
private stopAutoUpdate() {
if (this.updateInterval) {
clearInterval(this.updateInterval);
}
}
}
// 6. Advanced Service with Caching
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, timer } from 'rxjs';
export interface CacheItem<T> {
data: T;
timestamp: number;
ttl: number;
}
@Injectable({
providedIn: 'root'
})
export class CacheService {
private cache = new Map<string, CacheItem<any>>();
private defaultTTL = 300000; // 5 minutes
set<T>(key: string, data: T, ttl: number = this.defaultTTL): void {
this.cache.set(key, {
data,
timestamp: Date.now(),
ttl
});
}
get<T>(key: string): Observable<T | null> {
const item = this.cache.get(key);
if (!item) {
return of(null);
}
const now = Date.now();
if (now - item.timestamp > item.ttl) {
this.cache.delete(key);
return of(null);
}
return of(item.data);
}
clear(): void {
this.cache.clear();
}
clearExpired(): void {
const now = Date.now();
for (const [key, item] of this.cache.entries()) {
if (now - item.timestamp > item.ttl) {
this.cache.delete(key);
}
}
}
}
// 7. Advanced Directive
import { Directive, Input, HostListener } from '@angular/core';
import { ElementRef } from '@angular/core';
@Directive({
selector: '[appTooltip]',
host: {
'(mouseenter)': 'onMouseEnter($event)',
'(mouseleave)': 'onMouseLeave($event)'
}
})
export class TooltipDirective {
@Input('appTooltip') tooltipText: string;
private tooltipElement: HTMLElement;
private isVisible = false;
@HostListener('mouseenter', ['$event'])
onMouseEnter(event: MouseEvent) {
this.showTooltip(event.target as Element);
}
@HostListener('mouseleave', ['$event'])
onMouseLeave(event: MouseEvent) {
this.hideTooltip();
}
private showTooltip(element: Element) {
if (this.isVisible || !this.tooltipText) return;
this.createTooltipElement();
this.tooltipElement.textContent = this.tooltipText;
const rect = element.getBoundingClientRect();
this.tooltipElement.style.left = rect.left + 'px';
this.tooltipElement.style.top = (rect.bottom + 5) + 'px';
this.tooltipElement.style.visibility = 'visible';
this.isVisible = true;
}
private hideTooltip() {
if (this.tooltipElement) {
this.tooltipElement.style.visibility = 'hidden';
}
this.isVisible = false;
}
private createTooltipElement() {
if (this.tooltipElement) return;
this.tooltipElement = document.createElement('div');
this.tooltipElement.className = 'tooltip';
this.tooltipElement.style.cssText = `
position: fixed;
background: #333;
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 14px;
z-index: 1000;
pointer-events: none;
transition: opacity 0.3s;
opacity: 0;
`;
document.body.appendChild(this.tooltipElement);
}
}
// Usage in template:
// <div appTooltip="This is a tooltip">Hover over me</div>
// 8. Advanced Pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filterBy',
pure: false
})
export class FilterByPipe implements PipeTransform {
transform(items: any[], field: string, value: string): any[] {
if (!items || !field || !value) {
return items;
}
return items.filter(item =>
item[field] &&
item[field].toString().toLowerCase().includes(value.toLowerCase())
);
}
}
// Usage in template:
// *ngFor="let user of users | filterBy:'name':'searchTerm"
// <div *ngFor="let product of products | filterBy:'category':'electronics'">
// 9. Testing Setup
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { UserService } from './user.service';
describe('UserService', () => {
let service: UserService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [UserService]
});
service = TestBed.inject(UserService);
httpMock = TestBed.inject(HttpTestingController);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should retrieve users', () => {
const mockUsers = [
{ id: 1, name: 'Test User 1', email: '[email protected]', age: 25 },
{ id: 2, name: 'Test User 2', email: '[email protected]', age: 30 }
];
httpMock.expectOne('https://jsonplaceholder.typicode.com/users')
.flush(mockUsers);
service.getUsers().subscribe(users => {
expect(users).toEqual(mockUsers);
});
});
it('should handle errors', () => {
httpMock.expectOne('https://jsonplaceholder.typicode.com/users')
.flushError('Server error', { status: 500, statusText: 'Server Error' });
service.getUsers().subscribe(
() => fail('Expected error but got success'),
error => {
expect(error).toBeTruthy();
}
);
});
});
// 10. Main App Module
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { AuthInterceptor } from './auth.interceptor';
import { ErrorHandlingService } from './error-handling.service';
import { HelloWorldComponent } from './hello-world/hello-world.component';
import { GreetingComponent } from './greeting/greeting.component';
import { ItemListComponent } from './item-list/item-list.component';
import { UserFormComponent } from './user-form/user-form.component';
import { UserListComponent } from './user-list/user-list.component';
@NgModule({
declarations: [
AppComponent,
HelloWorldComponent,
GreetingComponent,
ItemListComponent,
UserFormComponent,
UserListComponent
],
imports: [
BrowserModule,
HttpClientModule,
RouterModule.forRoot(AppRoutingModule),
ReactiveFormsModule
],
providers: [
AuthInterceptor,
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
},
ErrorHandlingService
],
bootstrap: [AppComponent]
})
export class AppModule {}