Explanation: Angular CLI (Command Line Interface) is a tool to initialize, develop, scaffold, and maintain Angular applications. It simplifies the development process by handling build configurations, file generation, testing, and more.
npm install -g @angular/cli
ng new my-app
cd my-app
ng serve
Visit http://localhost:4200/ in your browser
Explanation: A component in Angular is a building block of the application that controls a part of the UI. It includes a class, an HTML template, and CSS styles.
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css']
})
export class ExampleComponent { }
Explanation: Data binding in Angular connects the data in your component logic to the UI. It can be one-way (component to view or view to component) or two-way.
<input [value]="name"><br/> <p>{{ name }}</p><br/> <button (click)="changeName()">Change Name</button><br/>
Explanation: A service in Angular is used to share logic and data between components. It's typically provided using dependency injection.
@Injectable({ providedIn: 'root' })
export class DataService {
getData() {
return ['Data1', 'Data2'];
}
}
Explanation: Angular routing allows navigation between different views or components in a single-page application using the Angular Router module.
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'about', component: AboutComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
Explanation: Angular directives are special markers on a DOM element that tell Angular to do something with that element or its children. Structural directives change the DOM layout (e.g., *ngIf
, *ngFor
), and attribute directives change appearance or behavior (e.g., ngClass
).
<div *ngIf="isVisible"><br> This text is conditionally visible.<br> </div><br> <ul><br> <li *ngFor="let item of items">{{ item }}</li><br> </ul>
Explanation: Angular supports template-driven and reactive forms. Template-driven forms use directives in the template for simple forms, and reactive forms provide more control with explicit form models in the component class.
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)"><br> <input name="username" ngModel required><br> <button type="submit">Submit</button><br> </form>
Explanation: Dependency injection (DI) is a design pattern where Angular automatically provides components or services with their required dependencies, improving modularity and testing.
constructor(private dataService: DataService) { }
Explanation: Angular modules (NgModules) group related components, directives, pipes, and services. They organize the app and manage dependencies. The root module bootstraps the app.
@NgModule({<br> declarations: [AppComponent],<br> imports: [BrowserModule],<br> bootstrap: [AppComponent]<br> })<br> export class AppModule { }
Explanation: Pipes transform displayed data in templates. Angular provides built-in pipes like date
and uppercase
, and you can create custom pipes.
{{ today | date:'fullDate' }}<br> {{ message | uppercase }}
Explanation: Parent and child components communicate via @Input()
(parent to child) and @Output()
with EventEmitter
(child to parent). Services and shared state are also used for communication.
// Parent template<br> <child-component [data]="parentData" (notify)="onNotify()"></child-component><br> // Child component<br> @Input() data: any;<br> @Output() notify = new EventEmitter<void>();<br> sendNotification() {<br> this.notify.emit();<br> }
Explanation: Lifecycle hooks are methods called by Angular during a component’s lifecycle such as creation, updates, and destruction. Common hooks include ngOnInit
and ngOnDestroy
.
ngOnInit() {<br> console.log('Component initialized');<br> }<br> ngOnDestroy() {<br> console.log('Component destroyed');<br> }
Explanation: Angular's HttpClient service is used to make HTTP requests. It returns Observables, allowing asynchronous handling of responses.
constructor(private http: HttpClient) { }<br> getData() {<br> return this.http.get<any>('https://api.example.com/data');<br> }
Explanation: Observables represent asynchronous data streams. Angular uses Observables for HTTP calls, reactive forms, and event handling. Components subscribe to Observables to react to data changes.
this.dataService.getData().subscribe(data => {<br> console.log(data);<br> });
Explanation: Change detection tracks data changes and updates the DOM accordingly. Angular’s default strategy runs after events and async tasks. You can optimize with ChangeDetectionStrategy.OnPush
.
@Component({<br> changeDetection: ChangeDetectionStrategy.OnPush<br> })
Explanation: Angular routing allows navigation between views or components by mapping URLs to components via routes defined in a routing module.
const routes: Routes = [<br> { path: 'home', component: HomeComponent },<br> { path: '', redirectTo: '/home', pathMatch: 'full' }<br> ];<br> @NgModule({<br> imports: [RouterModule.forRoot(routes)],<br> exports: [RouterModule]<br> })<br> export class AppRoutingModule { }
Explanation: Lazy loading delays loading feature modules until their routes are accessed, reducing initial bundle size and speeding up load time.
const routes: Routes = [<br> { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) }<br> ];
Explanation: Guards control access to routes. They determine if a route can be activated, deactivated, loaded, or if a user can leave a page.
@Injectable({ providedIn: 'root' })<br> export class AuthGuard implements CanActivate {<br> canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {<br> return this.authService.isLoggedIn();<br> }<br> }
Explanation: Angular Universal enables server-side rendering (SSR) of Angular apps for better SEO and faster initial load times.
// Setup Angular Universal with Angular CLI commands and configure server.ts for SSR.
Explanation: Custom directives let you add behavior to elements. You create them with @Directive
decorator and selector.
@Directive({ selector: '[appHighlight]' })<br> export class HighlightDirective {<br> constructor(private el: ElementRef) {<br> el.nativeElement.style.backgroundColor = 'yellow';<br> }<br> }
Explanation: Angular animations are built with the @angular/animations
package, using triggers and states to animate elements.
animations: [<br> trigger('openClose', [<br> state('open', style({ height: '200px', opacity: 1 })),<br> state('closed', style({ height: '100px', opacity: 0.5 })),<br> transition('open <> closed', [<br> animate('0.5s')<br> ])<br> ])<br> ]
Explanation: Validators ensure form input validity. Angular provides built-in validators like required
, minLength
, and you can create custom ones.
this.form = new FormGroup({<br> username: new FormControl('', [Validators.required, Validators.minLength(4)])<br> });
Explanation: Angular i18n supports translation of templates with i18n
attributes and extraction of translation files for different languages.
<h1 i18n>Welcome to our app!</h1>
Explanation: Angular CLI is a command line tool to generate components, services, modules, build, test and serve Angular apps quickly and consistently.
ng new my-app<br> ng generate component my-component<br> ng serve
Renderer2 is a service in Angular that allows you to manipulate DOM elements in a platform-independent way.<br> It provides methods like createElement, setAttribute, appendChild, etc.<br> This abstraction is useful for maintaining compatibility with different rendering environments like server-side rendering or Web Workers.<br> Example:<br> constructor(private renderer: Renderer2, private el: ElementRef) {}<br> ngOnInit() {<br> const button = this.renderer.createElement('button');<br> const text = this.renderer.createText('Click Me');<br> this.renderer.appendChild(button, text);<br> this.renderer.appendChild(this.el.nativeElement, button);<br> }<br>
NgZone is a service in Angular that allows you to execute code inside or outside of Angular’s zone.<br> This helps with performance optimizations by controlling change detection.<br> Useful for scenarios like avoiding unnecessary change detection when using 3rd-party libraries.<br> Example:<br> constructor(private ngZone: NgZone) {}<br> runOutsideAngularExample() {<br> this.ngZone.runOutsideAngular(() => {<br> setTimeout(() => {<br> this.ngZone.run(() => console.log('Back in Angular zone'));<br> }, 1000);<br> });<br> }<br>
ViewEncapsulation defines how styles are scoped to Angular components.<br> It can be set to Emulated (default), None, or ShadowDom.<br> - Emulated: emulates native scoping by adding unique attributes.<br> - None: styles are global.<br> - ShadowDom: uses native Shadow DOM.<br> Example:<br> @Component({<br> selector: 'app-example',<br> templateUrl: './example.component.html',<br> styleUrls: ['./example.component.css'],<br> encapsulation: ViewEncapsulation.Emulated<br> })<br>
To optimize performance in Angular apps, consider the following:<br> - Use OnPush change detection strategy.<br> - Lazy load modules.<br> - Avoid memory leaks with proper subscriptions.<br> - Use trackBy in *ngFor loops.<br> - Minify and tree-shake production builds with --prod flag.<br>
Use HttpInterceptor for global HTTP error handling.<br> Use try/catch in services and components for local error handling.<br> Example:
catchError((error: HttpErrorResponse) => {<br> console.error('Error occurred:', error);<br> return throwError(() => 'Something went wrong');<br> })<br>
Lifecycle hooks are methods that allow you to tap into key events in a component’s lifecycle.<br> Common hooks:<br> - ngOnInit(): called after component initialized.<br> - ngOnChanges(): when input properties change.<br> - ngOnDestroy(): before component is destroyed.<br> They are useful for initialization, cleanup, and responding to changes.<br>
Install Angular Universal:<br> npm install @nguniversal/express-engine --save<br> <br> Add Universal support:<br> ng add @nguniversal/express-engine<br> <br> Build the Universal app:<br> npm run build:ssr<br> <br> Serve the Universal app:<br> npm run serve:ssr<br>
const routes: Routes = [<br> { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) }<br> ];<br> <br> @NgModule({<br> imports: [RouterModule.forRoot(routes)],<br> exports: [RouterModule]<br> })<br> export class AppRoutingModule {}<br>
@Component({<br> selector: 'app-demo',<br> template: '<h1>{{ counter }}</h1>'<br> })<br> export class DemoComponent {<br> counter = 0;<br> increment() {<br> this.counter++;<br> }<br> }<br>
<p>{{ today | date:'longDate' }}</p><br> <p>{{ price | currency:'USD' }}</p><br>
@ViewChild('myInput') inputElement: ElementRef;<br> <br> ngAfterViewInit() {<br> this.inputElement.nativeElement.focus();<br> }<br> <br> <input #myInput type="text" /><br>
Angular NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. They help organize the application into cohesive blocks of functionality by grouping components, directives, pipes, and services. NgModules also define what components are public and available to other modules and help with dependency injection and lazy loading.
@NgModule({<br> declarations: [AppComponent, HomeComponent], <br> imports: [BrowserModule, FormsModule], <br> providers: [], <br> bootstrap: [AppComponent] <br> })<br> export class AppModule { }<br>
Dependency Injection (DI) in Angular is a design pattern in which a class requests dependencies from external sources rather than creating them. Angular provides built-in dependency injection to provide services and other dependencies to components and classes efficiently, promoting modularity and testability.
@Injectable({ providedIn: 'root' })<br> export class UserService { }<br> <br> @Component({ ... })<br> export class ProfileComponent {<br> constructor(private userService: UserService) { }<br> }<br>
Angular lifecycle hooks are methods that provide visibility into key moments in a component's or directive's lifecycle, such as creation, change detection, and destruction. Examples include ngOnInit()
, ngOnChanges()
, and ngOnDestroy()
. They let you tap into these phases to perform custom logic.
export class ExampleComponent implements OnInit, OnDestroy {<br> ngOnInit() {<br> console.log('Component initialized');<br> }<br> ngOnDestroy() {<br> console.log('Component destroyed');<br> }<br> }<br>
Routing guards in Angular control whether a route can be activated or deactivated. They are used to protect routes from unauthorized access or to warn users about unsaved changes before leaving a page.
@Injectable({ providedIn: 'root' })<br> export class AuthGuard implements CanActivate {<br> canActivate() {<br> return true; // logic to check authentication<br> }<br> }<br> <br> const routes: Routes = [<br> { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }<br> ];<br>
Custom pipes in Angular transform data in templates. You create a pipe class implementing PipeTransform
, decorate it with @Pipe
, and use it in templates with the pipe operator.
@Pipe({ name: 'reverse' })<br> export class ReversePipe implements PipeTransform {<br> transform(value: string): string {<br> return value.split('').reverse().join('');<br> }<br> }<br> <br> <!-- Usage in template --><br> <p>{{ 'hello' | reverse }}</p> <!-- Outputs: 'olleh' --><br>
Reactive forms in Angular provide a model-driven approach to handling form inputs and validations. You define form controls and groups programmatically and bind them to your template, allowing greater control and validation logic.
import { FormGroup, FormControl } from '@angular/forms';<br> <br> this.profileForm = new FormGroup({<br> firstName: new FormControl(''),<br> lastName: new FormControl('')<br> });<br> <br> <form [formGroup]="profileForm"><br> <input formControlName="firstName"><br> <input formControlName="lastName"><br> </form><br>
Template-driven forms use directives in the template to create and manage forms. They are simple to use for basic forms, relying mostly on Angular directives like ngModel
for two-way data binding and validations.
<form #myForm="ngForm"><br> <input name="username" ngModel required><br> <button [disabled]="!myForm.valid">Submit</button><br> </form><br>
Angular Change Detection checks for changes in the component’s data and updates the view accordingly. It runs automatically on events, timers, HTTP requests, and more. Developers can control detection strategy to optimize performance.
@Component({<br> changeDetection: ChangeDetectionStrategy.OnPush, <br> ...<br> })<br> export class ExampleComponent { }<br>
Optimizing Angular apps includes using OnPush change detection, lazy loading modules, trackBy in *ngFor, avoiding unnecessary bindings, using pure pipes, and minimizing bundle size through Ahead-of-Time (AOT) compilation and tree shaking.
<!-- Use trackBy in ngFor --><br> <div *ngFor="let item of items; trackBy: trackById">{{ item.name }}</div><br> <br> trackById(index: number, item: any) {<br> return item.id;<br> }<br>
Angular Elements allow Angular components to be packaged as reusable custom elements (web components) that can be used in any HTML page, even outside Angular apps. This increases interoperability with other frameworks.
import { createCustomElement } from '@angular/elements';<br> import { Injector } from '@angular/core';<br> <br> const el = createCustomElement(MyComponent, { injector: this.injector });<br> customElements.define('my-element', el);<br>
Angular Universal is a technology for server-side rendering (SSR) of Angular applications. It improves performance and SEO by rendering pages on the server before sending them to the client.
npm install @nguniversal/express-engine --save <br> ng add @nguniversal/express-engine <br>
Angular uses the HttpClient module to perform HTTP requests. It supports GET, POST, PUT, DELETE, and more, and returns Observables for asynchronous operations.
import { HttpClient } from '@angular/common/http';<br> <br> constructor(private http: HttpClient) { }<br> <br> this.http.get('https://api.example.com/data').subscribe(data => {<br> console.log(data);<br> });<br>
Angular CLI is a command-line interface tool to initialize, develop, scaffold, and maintain Angular applications. It automates many tasks like building, serving, testing, and deploying apps.
npm install -g @angular/cli <br> ng new my-app <br> ng serve <br>
Decorators in Angular are functions that modify classes or their members. They add metadata and behavior. Examples include @Component
, @Injectable
, @Input
, and @Output
.
@Component({<br> selector: 'app-sample',<br> templateUrl: './sample.component.html'<br> })<br> export class SampleComponent { }<br>
Directives are classes that add behavior to elements in Angular templates. Types: Structural (e.g., *ngIf
, *ngFor
) that change the DOM layout, and Attribute directives (e.g., ngClass
, ngStyle
) that change element appearance or behavior.
<div *ngIf="isVisible">Shown if isVisible is true</div><br> <div [ngClass]="{active: isActive}">Styled based on isActive</div><br>
Data sharing can be done via Input and Output decorators for parent-child communication, shared services with RxJS Subjects for unrelated components, or by using local storage or route parameters.
<!-- Parent passes data --><br> <child-comp [childData]="parentData"></child-comp><br> <br> <!-- Child emits event --><br> @Output() notify = new EventEmitter<string>();<br> this.notify.emit('message');<br>
ViewChild decorator lets you access a child component, directive, or DOM element from the parent component class to interact directly with it.
@ViewChild('myInput') inputElement: ElementRef;<br> ngAfterViewInit() {<br> this.inputElement.nativeElement.focus();<br> }<br> <input #myInput><br>
NgZone allows Angular to know when to run change detection by running code inside or outside Angular's zone, improving performance by limiting change detection cycles.
constructor(private ngZone: NgZone) { }<br> <br> this.ngZone.runOutsideAngular(() => {<br> // code that doesn’t trigger change detection<br> });<br>
RxJS is a library for reactive programming using Observables. Angular uses RxJS to handle asynchronous operations like HTTP requests, event handling, and reactive forms.
import { Observable, of } from 'rxjs';<br> <br> const obs$: Observable<number> = of(1, 2, 3);<br> obs$.subscribe(value => console.log(value));<br>
Lazy loading loads feature modules only when needed, reducing initial load time. It's configured in routing using the loadChildren
property.
const routes: Routes = [<br> { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) }<br> ];<br>
Angular Material is a UI component library following Material Design guidelines. Add it using Angular CLI and import modules.
ng add @angular/material <br> import { MatButtonModule } from '@angular/material/button';<br> @NgModule({<br> imports: [MatButtonModule]<br> })<br> export class AppModule { }<br>
Pipes transform data in templates. Angular provides built-in pipes like date, uppercase, lowercase. Custom pipes can be created to format or transform data.
import { Pipe, PipeTransform } from '@angular/core';<br> <br> @Pipe({ name: 'exclaim' })<br> export class ExclaimPipe implements PipeTransform {<br> transform(value: string): string {<br> return value + '!!!';<br> }<br> }<br> <br> <!-- usage --><br> {{ 'Hello' | exclaim }} <!-- Output: Hello!!! --><br>
Template-driven forms rely on directives in templates and are simpler for basic forms. Reactive forms use explicit model-driven form control and offer more power and flexibility.
<!-- Template-driven --><br> <form #f="ngForm"><br> <input name="email" ngModel required><br> </form><br> <br> <!-- Reactive --><br> this.form = this.fb.group({<br> email: ['', Validators.required]<br> });<br>
Implement a global error handler by creating a class implementing ErrorHandler
and providing it in the module.
import { ErrorHandler, Injectable } from '@angular/core';<br> <br> @Injectable()<br> export class GlobalErrorHandler implements ErrorHandler {<br> handleError(error: any) {<br> console.error('Global error:', error);<br> }<br> }<br> <br> @NgModule({<br> providers: [{ provide: ErrorHandler, useClass: GlobalErrorHandler }]<br> })<br> export class AppModule { }<br>
Change Detection in Angular tracks changes in component data and updates the DOM accordingly. It runs automatically on events, HTTP calls, timers, or manually via ChangeDetectorRef.
import { ChangeDetectorRef } from '@angular/core';<br> <br> constructor(private cd: ChangeDetectorRef) { }<br> <br> someAsyncEvent() {<br> this.data = newData;<br> this.cd.detectChanges(); // manually trigger change detection<br> }<br>
Dependency Injection (DI) is a design pattern Angular uses to provide components with the services or objects they need, rather than having components create them. Angular injects dependencies via constructors.
import { Injectable } from '@angular/core';<br> <br> @Injectable({ providedIn: 'root' })<br> export class DataService {<br> getData() {<br> return ['Angular', 'React', 'Vue'];<br> }<br> }<br> <br> import { Component } from '@angular/core';<br> import { DataService } from './data.service';<br> <br> @Component({<br> selector: 'app-root',<br> template: '<ul><li *ngFor="let item of data">{{item}}</li></ul>'<br> })<br> export class AppComponent {<br> data: string[];<br> constructor(private dataService: DataService) {<br> this.data = this.dataService.getData();<br> }<br> }<br>
Lifecycle hooks are methods called at specific moments of a component's life. Key hooks include:
- ngOnInit: Called once after first ngOnChanges, good for initialization.
- ngOnChanges: Called on input property changes.
- ngOnDestroy: Called before component is destroyed, used for cleanup.
import { Component, OnInit, OnDestroy, Input, OnChanges, SimpleChanges } from '@angular/core';<br> <br> @Component({<br> selector: 'app-demo',<br> template: '<p>Check console for lifecycle logs</p>'<br> })<br> export class DemoComponent implements OnInit, OnDestroy, OnChanges {<br> @Input() data!: string;<br> <br> ngOnInit() {<br> console.log('ngOnInit called');<br> }<br> <br> ngOnChanges(changes: SimpleChanges) {<br> console.log('ngOnChanges', changes);<br> }<br> <br> ngOnDestroy() {<br> console.log('ngOnDestroy called');<br> }<br> }<br>
Directives are classes that add behavior to elements in Angular templates.
Types:
- Component directives (with template)
- Structural directives (change DOM layout like *ngIf, *ngFor)
- Attribute directives (change element appearance or behavior, e.g., ngClass)
<!-- Structural Directive --><br> <div *ngIf="isVisible">Visible content</div><br> <br> <!-- Attribute Directive --><br> <div [ngClass]="{ 'highlight': isActive }">Highlight me</div><br>
Angular routing enables navigation between views or components using URLs. Routes are configured with paths and components, and RouterModule
manages navigation.
import { NgModule } from '@angular/core';<br> import { RouterModule, Routes } from '@angular/router';<br> import { HomeComponent } from './home.component';<br> import { AboutComponent } from './about.component';<br> <br> const routes: Routes = [<br> { path: '', component: HomeComponent },<br> { path: 'about', component: AboutComponent }<br> ];<br> <br> @NgModule({<br> imports: [RouterModule.forRoot(routes)],<br> exports: [RouterModule]<br> })<br> export class AppRoutingModule { }<br> <br> <!-- in app.component.html --><br> <nav><br> <a routerLink="">Home</a><br> <a routerLink="about">About</a><br> </nav><br> <router-outlet></router-outlet><br>
Services are classes to share data or logic across components. Provided at root or module/component level for dependency injection.
import { Injectable } from '@angular/core';<br> <br> @Injectable({ providedIn: 'root' })<br> export class LoggingService {<br> log(message: string) {<br> console.log('Log:', message);<br> }<br> }<br> <br> import { Component } from '@angular/core';<br> import { LoggingService } from './logging.service';<br> <br> @Component({<br> selector: 'app-demo',<br> template: '<button (click)="logMessage()">Log</button>'<br> })<br> export class DemoComponent {<br> constructor(private logger: LoggingService) { }<br> logMessage() {<br> this.logger.log('Button clicked');<br> }<br> }<br>
Angular modules organize related components, directives, pipes, and services into cohesive blocks. The root module bootstraps the app.
import { NgModule } from '@angular/core';<br> import { BrowserModule } from '@angular/platform-browser';<br> import { AppComponent } from './app.component';<br> import { FormsModule } from '@angular/forms';<br> <br> @NgModule({<br> declarations: [AppComponent],<br> imports: [BrowserModule, FormsModule],<br> providers: [],<br> bootstrap: [AppComponent]<br> })<br> export class AppModule { }<br>
Custom pipes transform data in templates. Create by implementing PipeTransform interface and adding @Pipe decorator.
import { Pipe, PipeTransform } from '@angular/core';<br> <br> @Pipe({ name: 'reverse' })<br> export class ReversePipe implements PipeTransform {<br> transform(value: string): string {<br> return value.split('').reverse().join('');<br> }<br> }<br> <br> <!-- usage in template --><br> {{ 'Angular' | reverse }} <!-- Output: ralugnA --><br>
Angular CLI is a command-line interface tool to create, build, and manage Angular projects easily.
ng new my-app <!-- create a new project --><br> ng serve <!-- run development server --><br> ng generate component my-component <!-- generate a new component --><br> ng build <!-- build project for production --><br> ng test <!-- run tests --><br>
Communication between components can happen via:
- Input and Output decorators for parent-child interaction
- Shared services with RxJS for unrelated components
import { Component, Input, Output, EventEmitter } from '@angular/core';<br> <br> @Component({<br> selector: 'child-comp',<br> template: '<button (click)="notifyParent()">Notify</button>'<br> })<br> export class ChildComponent {<br> @Input() message!: string;<br> @Output() notify = new EventEmitter<string>();<br> notifyParent() {<br> this.notify.emit('Child says hi');<br> }<br> }<br> <br> @Component({<br> selector: 'parent-comp',<br> template: '<child-comp [message]="parentMessage" (notify)="onNotify($event)"></child-comp>'<br> })<br> export class ParentComponent {<br> parentMessage = 'Hello Child';<br> onNotify(msg: string) {<br> console.log('Received:', msg);<br> }<br> }<br>
AOT compiles Angular HTML and TypeScript code during build time instead of runtime, leading to faster rendering, smaller bundles, and earlier error detection.
<!-- Build with AOT enabled (default in production) --><br> ng build --prod <br>
Angular's change detection tracks changes in component data and updates the DOM accordingly. It runs after asynchronous events like user input, HTTP calls, or timers.
@Component({<br> selector: 'app-demo',<br> template: '<p>Count: {{count}}</p><button (click)="increment()">Add</button>'<br> })<br> export class DemoComponent {<br> count = 0;<br> <br> increment() {<br> this.count++; // triggers change detection to update view<br> }<br> }<br>
Guards control access to routes. They decide if navigation is allowed or not, useful for authentication and authorization.
import { Injectable } from '@angular/core';<br> import { CanActivate, Router } from '@angular/router';<br> <br> @Injectable({ providedIn: 'root' })<br> export class AuthGuard implements CanActivate {<br> constructor(private router: Router) {}<br> <br> canActivate(): boolean {<br> const loggedIn = false; // simulate auth check<br> if (!loggedIn) {<br> this.router.navigate(['/login']);<br> return false;<br> }<br> return true;<br> }<br> }<br>
Angular provides two form approaches:
- Template-driven forms use directives in templates; simple but less scalable.
- Reactive forms are more powerful, using explicit model-driven approach and FormGroup/FormControl classes.
<!-- Template-driven form --><br> <form #form="ngForm" (ngSubmit)="submit(form.value)"><br> <input name="email" ngModel required /><br> <button type="submit">Submit</button><br> </form><br> <br> <!-- Reactive form in component.ts --><br> import { FormGroup, FormControl, Validators } from '@angular/forms';<br> <br> form = new FormGroup({<br> email: new FormControl('', [Validators.required, Validators.email])<br> });<br> <br> submit() {<br> console.log(this.form.value);<br> }<br>
Ways to optimize:
- Use OnPush change detection
- Lazy load modules
- Avoid unnecessary bindings
- Use trackBy with *ngFor
- Use Angular CLI production build with AOT and minification
Angular Universal enables server-side rendering (SSR) of Angular apps, improving SEO and initial load time.
Lazy loading loads feature modules only when needed, improving startup time.
const routes: Routes = [<br> { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) }<br> ];<br>
HttpClient is used to communicate with backend services over HTTP. It supports observable-based APIs for requests.
import { HttpClient } from '@angular/common/http';<br> <br> constructor(private http: HttpClient) {}<br> <br> getUsers() {<br> this.http.get('https://api.example.com/users').subscribe(data => {<br> console.log(data);<br> });<br> }<br>
Angular i18n provides tools to extract text and translate it, supporting multiple locales with built-in pipes and message IDs.
A Subject is both an observable and an observer. It can multicast values to multiple subscribers, useful for event emitters and shared data streams.
import { Subject } from 'rxjs';<br> <br> const subject = new Subject<number>();<br> subject.subscribe(val => console.log('Observer 1:', val));<br> subject.next(1); // emits 1 to all subscribers<br>
Common ways:
- @Input() and @Output() for parent-child communication
- Services with RxJS Subjects for sibling or unrelated components
- Using a shared service singleton with observable streams
- ViewChild accesses a child component/directive/view inside the component template.
- ContentChild accesses projected content (inside <ng-content>) passed from a parent component.
Pipes transform data in templates. You can create custom pipes by implementing PipeTransform.
import { Pipe, PipeTransform } from '@angular/core';<br> <br> @Pipe({ name: 'exclaim' })<br> export class ExclaimPipe implements PipeTransform {<br> transform(value: string): string {<br> return value + '!!!';<br> }<br> }<br> <br> <!-- usage in template --><br> <p>{{ 'Hello' | exclaim }}</p> <!-- outputs: Hello!!! --><br>
Angular CLI is a command-line interface tool to create, build, and maintain Angular projects.
Common commands:
- ng new <project-name> : create new project
- ng serve : serve app locally
- ng generate component <name> : create a new component
- ng build : build app for production
Use HttpInterceptor to catch errors from HTTP calls and handle them globally.
import { Injectable } from '@angular/core';<br> import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';<br> import { Observable, throwError } from 'rxjs';<br> import { catchError } from 'rxjs/operators';<br> <br> @Injectable()<br> export class ErrorInterceptor implements HttpInterceptor {<br> intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {<br> return next.handle(req).pipe(<br> catchError((error: HttpErrorResponse) => {<br> // handle error here globally<br> alert('An error occurred: ' + error.message);<br> return throwError(error);<br> })<br> );<br> }<br> }<br>
Angular Material is a UI component library following Material Design principles. To add it:
Run: ng add @angular/material
Then import modules like MatButtonModule
into your NgModule.
import { MatButtonModule } from '@angular/material/button';<br> <br> @NgModule({<br> imports: [MatButtonModule]<br> })<br> export class AppModule {}<br>
Template-driven forms are simpler, using directives in the template for form handling and validation. They rely heavily on Angular's two-way data binding.
Reactive forms are more powerful and scalable, defined programmatically in the component class using FormControl and FormGroup, providing explicit and synchronous access to the form data, with better control over validation.
<!-- Template-driven form example --><br/> <form #myForm="ngForm"><br/> <input name="username" ngModel required /><br/> <button type="submit">Submit</button><br/> </form><br/> <!-- Reactive form example (component.ts) --><br/> import { FormGroup, FormControl, Validators } from '@angular/forms';<br/> myForm = new FormGroup({<br/> username: new FormControl('', Validators.required)<br/> });<br/>
Lazy loading allows Angular modules to be loaded on demand rather than at app startup, improving load time and performance. It is implemented by using the loadChildren property in the routing configuration.
const routes: Routes = [<br/> { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) }<br/> ];<br/>
Angular lifecycle hooks allow you to tap into key moments in a component or directive's lifecycle for initialization, change detection, and cleanup. Common hooks include ngOnInit, ngOnChanges, ngOnDestroy.
export class MyComponent implements OnInit, OnDestroy {<br/> ngOnInit() {<br/> // Called once after component initialization<br/> }<br/> ngOnDestroy() {<br/> // Cleanup before component is destroyed<br/> }<br/> }<br/>
Angular change detection is the mechanism that tracks changes in data models and updates the view accordingly. It runs after events such as user input, HTTP responses, or timer events. Angular uses zones to detect these changes and runs the detection cycle.
<!-- Angular automatically detects changes and updates views --><br/> <p>{{ title }}</p><br/> <button (click)="title = 'New Title'">Change Title</button><br/>
Performance can be optimized by lazy loading modules, using OnPush change detection, trackBy in *ngFor, avoiding unnecessary bindings, and using Ahead-Of-Time (AOT) compilation.
<!-- Use trackBy in *ngFor --><br/> <div *ngFor="let item of items; trackBy: trackById">{{ item.name }}</div><br/> trackById(index: number, item: any) {<br/> return item.id;<br/> }<br/>
Angular Universal is a technology for server-side rendering (SSR) Angular apps, improving SEO and perceived performance by rendering pages on the server before sending them to the client.
<!-- Setup uses Angular Universal schematics --><br/> ng add @nguniversal/express-engine<br/>
Angular uses hierarchical dependency injection, where services can be provided at different levels (root, module, component). Angular injects service instances automatically into constructors based on providers configuration.
@Injectable({ providedIn: 'root' })<br/> export class ApiService { }<br/> constructor(private apiService: ApiService) { }<br/>
Pipes transform displayed data in templates, like formatting dates, currencies, or filtering lists. Angular provides built-in pipes and allows creating custom ones.
<p>{{ today | date:'fullDate' }}</p><br/> <p>{{ price | currency:'USD' }}</p><br/>
A custom pipe is created by implementing PipeTransform interface and decorating the class with @Pipe.
import { Pipe, PipeTransform } from '@angular/core';<br/> @Pipe({ name: 'exclaim' })<br/> export class ExclaimPipe implements PipeTransform {<br/> transform(value: string): string {<br/> return value + '!!!';<br/> }<br/> }<br/>
Directives are classes that add behavior to elements in Angular templates. Types include:
- Component directives (with templates)
- Structural directives (change DOM layout, e.g. *ngIf, *ngFor)
- Attribute directives (change appearance or behavior, e.g. ngClass, ngStyle)
<div *ngIf="showDiv">Shown if true</div><br/> <div [ngClass]="{ 'active': isActive }">Styled conditionally</div><br/>
Components communicate via:
- Input properties (@Input) to pass data from parent to child
- Output properties (@Output) with EventEmitter to send events from child to parent
- Shared service for unrelated components
<!-- Parent Template --><br/> <child-comp [data]="parentData" (notify)="onNotify()"></child-comp><br/> <!-- Child Component --><br/> @Input() data: string;<br/> @Output() notify = new EventEmitter<void>();<br/> this.notify.emit();<br/>
Angular Router enables navigation among views or components. Routes are configured in a Routes array, specifying path and component.
const routes: Routes = [<br/> { path: '', component: HomeComponent },<br/> { path: 'about', component: AboutComponent }<br/> ];<br/> @NgModule({<br/> imports: [RouterModule.forRoot(routes)],<br/> exports: [RouterModule]<br/> })<br/> export class AppRoutingModule { }<br/>
The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. It also unsubscribes automatically when the component is destroyed.
<p>{{ dataObservable | async }}</p><br/>
An NgModule organizes related components, directives, pipes, and services into cohesive blocks. It defines which components belong, what dependencies are imported, and which components are exported.
@NgModule({<br/> declarations: [AppComponent, HomeComponent],<br/> imports: [BrowserModule],<br/> providers: [],<br/> bootstrap: [AppComponent]<br/> })<br/> export class AppModule { }<br/>
Use route guards like CanActivate to control access. Guards implement interfaces and return true/false or a URL to redirect.
@Injectable({ providedIn: 'root' })<br/> export class AuthGuard implements CanActivate {<br/> constructor(private authService: AuthService, private router: Router) { }<br/> canActivate(): boolean {<br/> if (this.authService.isLoggedIn()) {<br/> return true;<br/> } else {<br/> this.router.navigate(['/login']);<br/> return false;<br/> }<br/> }<br/> }<br/>
Observables represent streams of data that can be observed asynchronously. Angular uses RxJS Observables for HTTP calls, event handling, and reactive forms.
import { Observable } from 'rxjs';<br/> const data$: Observable<number> = new Observable(observer => {<br/> observer.next(1);<br/> observer.next(2);<br/> observer.complete();<br/> });<br/> data$.subscribe(value => console.log(value));<br/>
Angular's HttpClient service is used to make HTTP requests. It returns Observables which can be subscribed to get the response asynchronously.
import { HttpClient } from '@angular/common/http';<br/> constructor(private http: HttpClient) { }<br/> this.http.get<any>('https://api.example.com/data')<br/> .subscribe(response => console.log(response));<br/>
The constructor is for dependency injection and minimal initialization.
ngOnInit is a lifecycle hook called after Angular initializes the component’s input properties, suitable for complex initialization and fetching data.
Implement ErrorHandler interface in a class and provide it globally. This captures uncaught exceptions and allows centralized error handling.
import { ErrorHandler, Injectable } from '@angular/core';<br/> @Injectable()<br/> export class GlobalErrorHandler implements ErrorHandler {<br/> handleError(error: any) {<br/> console.error('Global error:', error);<br/> // Show user-friendly message or log error remotely<br/> }<br/> }<br/> providers: [{ provide: ErrorHandler, useClass: GlobalErrorHandler }],<br/>
Explanation: @Input()
is used to pass data from a parent component to a child component. @Output()
is used to emit events from a child component to the parent component.
// Parent component template <child-component [childProperty]="parentValue" (childEvent)="handleEvent($event)"></child-component> // Child component @Input() childProperty: string; @Output() childEvent = new EventEmitter<string>(); triggerEvent() { this.childEvent.emit('Data from child'); }
Explanation: Two-way data binding is enabled in Angular using the [(ngModel)]
directive, which allows synchronization of data between the component class and the template.
// In the component export class MyComponent { name: string = 'Angular'; } // In the template <input [(ngModel)]="name"> <p>Hello, {{ name }}!</p>
Explanation: NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. Each app has a root module, and it can have many feature modules.
@NgModule({ declarations: [AppComponent], imports: [BrowserModule], bootstrap: [AppComponent] }) export class AppModule {}
Explanation: Angular uses a hierarchical dependency injection system to supply components with services or objects they need.
@Injectable({ providedIn: 'root' }) export class LoggerService { log(message: string) { console.log(message); } } @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent { constructor(private logger: LoggerService) { logger.log('App started'); } }
Explanation: The ReactiveFormsModule allows you to build forms programmatically and manage them in the component class with form control objects.
import { FormGroup, FormControl } from '@angular/forms'; export class MyFormComponent { form = new FormGroup({ name: new FormControl(''), email: new FormControl('') }); onSubmit() { console.log(this.form.value); } } // In the template <form [formGroup]="form" (ngSubmit)="onSubmit()"> <input formControlName="name"> <input formControlName="email"> <button type="submit">Submit</button> </form>
Explanation: The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. It also marks the component for check when a new value is emitted.
// In the component obs$ = of('Hello from Observable'); // In the template <p>{{ obs$ | async }}</p>
Explanation: Template-driven forms are created in the template using directives. Reactive forms are created in the component class with form control instances.
// Template-driven example <form #form="ngForm"> <input name="name" ngModel> </form> // Reactive example form = new FormGroup({ name: new FormControl('') });
Explanation: You can apply custom validation by passing a custom validator function to the form control's constructor or using the setValidators method.
function noSpecialChars(control: FormControl): ValidationErrors | null { return /[^a-zA-Z0-9]/.test(control.value) ? { 'specialChars': true } : null; } form = new FormGroup({ username: new FormControl('', noSpecialChars) });
Explanation: Lifecycle hooks are special methods in Angular components that allow you to tap into key events during the component's life, such as initialization, changes, and destruction.
export class MyComponent implements OnInit, OnDestroy { ngOnInit() { console.log('Component initialized'); } ngOnDestroy() { console.log('Component destroyed'); } }
Explanation: The trackBy function helps Angular identify which items in a list have changed, added, or removed. This improves performance by reducing DOM manipulation.
trackByFn(index: number, item: any): number { return item.id; } // Template <div *ngFor="let item of items; trackBy: trackByFn"> {{ item.name }} </div>
Explanation: Angular provides HttpClient in the @angular/common/http
module to make HTTP requests to external APIs.
import { HttpClient } from '@angular/common/http'; constructor(private http: HttpClient) {} getData() { this.http.get('https://api.example.com/data') .subscribe(data => console.log(data)); }