Angular integrates deeply with RxJS for reactive programming and introduces Signals for fine-grained reactivity. This chapter explores advanced libraries, authentication, internationalization, and standalone components.
RxJS (Reactive Extensions for JavaScript) is the foundation of Angular's asynchronous and event-based programming model.
.next()Operators transform, filter, and combine Observable streams.
import { of, fromEvent } from 'rxjs';
import { map, filter, debounceTime, switchMap } from 'rxjs/operators';
of(1, 2, 3, 4, 5).pipe(
filter(x => x % 2 === 0),
map(x => x * 10)
).subscribe(console.log); // 20, 40
// Search input with debounce
fromEvent(input, 'input').pipe(
debounceTime(300),
switchMap(() => this.searchService.search(input.value))
).subscribe(results => this.results = results);
switchMap cancels the previous inner observable when a new value arrives — ideal for typeahead searches.Signals provide a new reactive primitive for Angular. They are simpler than RxJS for state management and integrate deeply with change detection.
import { signal, computed, effect, input, output } from '@angular/core';
const count = signal(0);
const doubled = computed(() => count() * 2);
effect(() => console.log('Count:', count()));
// In a component
export class CounterComponent {
value = input(0);
changed = output<number>();
increment() {
this.value.update(v => v + 1);
this.changed.emit(this.value());
}
}
JSON Web Tokens (JWT) are commonly used for stateless authentication. Store tokens in localStorage and attach them via HTTP interceptors.
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
const token = localStorage.getItem('token');
if (token) {
req = req.clone({
headers: req.headers.set('Authorization', `Bearer ${token}`)
});
}
return next.handle(req);
}
}
@Injectable({ providedIn: 'root' })
export class AuthService {
private user = signal<User | null>(null);
isLoggedIn = computed(() => this.user() !== null);
login(credentials: Credentials) {
return this.http.post<{ token: string }>('/api/login', credentials).pipe(
tap(res => {
localStorage.setItem('token', res.token);
this.user.set(this.decodeToken(res.token));
})
);
}
}
Protect routes using CanActivate guard.
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
constructor(private auth: AuthService, private router: Router) {}
canActivate(): boolean {
if (!this.auth.isLoggedIn()) {
this.router.navigate(['/login']);
return false;
}
return true;
}
}
Use @angular/localize to translate your application into multiple languages.
ng add @angular/localize
// In template
<h1 i18n="Greeting|An introduction greeting">Hello!</h1>
// Extract messages
ng extract-i18n --output-path src/locale
Standalone components eliminate the need for NgModule. Use standalone: true and bootstrapApplication.
@Component({
standalone: true,
imports: [CommonModule, RouterModule],
template: `<h1>Standalone!</h1>`
})
export class AppComponent {}
// main.ts
bootstrapApplication(AppComponent, {
providers: [provideHttpClient(), provideRouter(routes)]
});
Run CPU-intensive tasks off the main thread with web workers.
const worker = new Worker(new URL('./app.worker', import.meta.url));
worker.postMessage({ data: heavyArray });
worker.onmessage = ({ data }) => console.log(data);
Angular Universal enables server-side rendering for better SEO and initial load performance.
ng add @nguniversal/express-engine
bootstrapApplication and configure the router provider. Add an authentication guard to protect a dashboard route.