Angular Basics
Click ★ if you like the project. Your contributions are heartily ♡ welcome.
Projects
Table of Contents
# 1. INTRODUCTION
Q. What is Angular?
Angular is an open-source, component-based front-end web application framework developed and maintained by Google. It is written in TypeScript and provides a complete platform for building single-page applications (SPAs), including:
- A powerful component-based architecture for building reusable UI pieces
- Declarative templates with two-way data binding
- A built-in dependency injection system
- End-to-end tooling via Angular CLI
- Integrated support for routing, forms, HTTP, testing, and animations
Angular vs AngularJS:
| Feature |
AngularJS (1.x) |
Angular (2+) |
| Language |
JavaScript |
TypeScript |
| Architecture |
MVC |
Component-based |
| Mobile support |
Not optimized |
Mobile-first |
| Performance |
Digest cycle |
Zone.js + CD tree |
| CLI |
No official CLI |
Angular CLI |
| Rendering |
Client-side only |
SSR via Universal |
Q. What are the key features of Angular?
| Feature |
Description |
| Component-based architecture |
UI is composed of self-contained, reusable components |
| TypeScript |
Provides static typing, interfaces, and decorators for early error detection |
| Data Binding |
One-way, two-way, event, and property binding between component class and template |
| Dependency Injection |
Built-in DI system for providing and consuming services across the app |
| Directives |
Extend HTML with structural (*ngIf, *ngFor) and attribute directives |
| Pipes |
Transform data in templates (date, currency, async, custom pipes) |
| Routing |
Client-side navigation with lazy loading, guards, and resolvers |
| RxJS / Reactive Programming |
Asynchronous data streams via Observables throughout the framework |
| Angular CLI |
Scaffolding, building, testing, and deploying Angular apps |
| Ivy Renderer |
Modern, tree-shakable compilation and rendering engine (default since Angular 9) |
| Angular Universal |
Server-side rendering for SEO and performance |
| PWA Support |
Service workers via @angular/pwa |
| i18n |
Built-in internationalization and localization tooling |
Q. What is the difference between AngularJS and Angular?
AngularJS refers to Angular version 1.x, while Angular (without the “JS”) refers to versions 2 and above, which is a complete rewrite.
| Aspect |
AngularJS (1.x) |
Angular (2+) |
| Release year |
2010 |
2016 |
| Language |
JavaScript |
TypeScript |
| Architecture |
MVC (Model-View-Controller) |
Component-based |
| Data binding |
Two-way (ng-model) |
One-way by default; two-way opt-in via [(ngModel)] |
| Dependency Injection |
Uses $injector |
Hierarchical injector |
| Mobile |
Not designed for mobile |
Mobile-first design |
| Routing |
ngRoute / UI-Router |
@angular/router |
| Change detection |
Dirty checking (digest cycle) |
Zone.js + unidirectional change detection tree |
| Performance |
Slower for large apps |
Significantly faster with OnPush and Ivy |
| Tooling |
Grunt/Gulp |
Angular CLI |
| Testing |
Karma/Jasmine |
Karma/Jasmine + TestBed |
| Community support |
End of Life (Dec 2021) |
Actively maintained by Google |
Q. What are the building blocks of an Angular application?
An Angular application is built from the following core building blocks:
1. Modules (NgModule) — Organise the application into cohesive feature blocks.
@NgModule({
declarations: [AppComponent], // Components, Directives, Pipes
imports: [BrowserModule], // Other modules
providers: [UserService], // Services
bootstrap: [AppComponent] // Root component
})
export class AppModule {}
2. Components — The fundamental UI building block; each manages a view.
3. Templates — HTML with Angular-specific syntax for binding and directives.
4. Metadata / Decorators — Decorators (@Component, @NgModule, etc.) provide Angular with configuration information.
5. Data Binding — Communication between the component class and its template.
6. Directives — Classes that add behaviour to DOM elements.
7. Services — Classes that encapsulate business logic, data access, and reusable functionality.
8. Dependency Injection — Provides instances of services to classes that need them.
9. Routing — Navigates between views without full page reloads.
10. Pipes — Transform displayed values in templates.
Q. What is TypeScript and why does Angular use it?
TypeScript is a statically-typed superset of JavaScript developed by Microsoft. Angular uses TypeScript for the following benefits:
1. Static typing — Catch type errors at compile time rather than runtime.
// JavaScript — error only discovered at runtime
function add(a, b) { return a + b; }
add(1, '2'); // Returns '12' (string concatenation — silent bug)
// TypeScript — error caught immediately by the compiler
function addNumbers(a: number, b: number): number { return a + b; }
// addNumbers(1, '2'); ERROR: Argument of type 'string' is not assignable to 'number'
2. Interfaces & Types — Define contracts for data structures.
interface User {
id: number;
name: string;
email: string;
role?: 'admin' | 'user'; // Optional union type
}
3. Decorators — Enable Angular's metadata system (@Component, @Injectable, @Input, etc.).
4. Better IDE support — Rich autocompletion, inline documentation, and refactoring tools.
5. Access modifiers — public, private, protected enforce encapsulation.
6. Generics — Write reusable, type-safe code.
getItems<T>(url: string): Observable<T[]> {
return this.http.get<T[]>(url);
}
Q. What is the Angular component lifecycle?
Every Angular component goes through a sequence of lifecycle phases managed by Angular's change detection mechanism:
Constructor → ngOnChanges → ngOnInit → ngDoCheck
→ ngAfterContentInit → ngAfterContentChecked
→ ngAfterViewInit → ngAfterViewChecked
→ (repeats on updates)
→ ngOnDestroy
When to use which hook:
| Hook |
Best Used For |
constructor |
Dependency injection; avoid side effects |
ngOnChanges |
React to @Input() changes |
ngOnInit |
Component initialisation, first data fetch |
ngDoCheck |
Custom change detection logic |
ngAfterContentInit |
Access projected content (@ContentChild) |
ngAfterViewInit |
Access component's DOM / child components (@ViewChild) |
ngOnDestroy |
Unsubscribe, clear timers, release resources |
Q. What is two-way data binding in Angular?
Two-way data binding synchronises data between the component class and the template in both directions simultaneously. Angular implements it using the banana-in-a-box syntax [()], which combines property binding [] and event binding ().
@Component({
selector: 'app-root',
template: `
<input [(ngModel)]="username" placeholder="Enter name">
<p>Hello, {{ username }}!</p>
`
})
export class AppComponent {
username = '';
}
Under the hood, [(ngModel)] is shorthand for:
<input [ngModel]="username" (ngModelChange)="username = $event">
Comparison of binding types:
| Type |
Syntax |
Direction |
| Interpolation |
{{ value }} |
Class → Template |
| Property binding |
[property]="expr" |
Class → Template |
| Event binding |
(event)="handler()" |
Template → Class |
| Two-way binding |
[(ngModel)]="prop" |
Both directions |
Q. What is a Single Page Application (SPA) and how does Angular enable it?
A Single Page Application is a web application that loads a single HTML page and dynamically updates the view as the user interacts with the app, without full page reloads.
How Angular enables SPA:
- Angular Router — Intercepts URL changes and renders the matching component without a full page reload.
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent },
{ path: 'users/:id', component: UserDetailComponent }
];
- Component-based rendering — Only the components that need to update are re-rendered.
- Lazy loading — Feature modules are downloaded on demand, keeping the initial bundle small.
SPA benefits:
| Benefit |
Description |
| Speed |
Subsequent navigation is near-instant (no server round-trips for HTML) |
| Better UX |
Smooth transitions; app state is preserved between views |
| Reduced server load |
Server serves API data (JSON), not rendered HTML pages |
| Native-app feel |
Animations, offline support, PWA capabilities |
SPA trade-offs:
- Initial load may be heavier (mitigated by lazy loading and code splitting)
- SEO requires server-side rendering (Angular Universal)
- Browser history management must be handled explicitly
Q. What are decorators in Angular?
Decorators are a TypeScript feature that attach metadata to classes, methods, properties, and parameters. Angular uses decorators extensively to configure its building blocks.
Class decorators:
@Component({ selector: 'app-root', templateUrl: './app.component.html' })
export class AppComponent { }
@NgModule({ declarations: [...], imports: [...] })
export class AppModule { }
@Injectable({ providedIn: 'root' })
export class DataService { }
@Pipe({ name: 'titleCase' })
export class TitleCasePipe { }
@Directive({ selector: '[appHighlight]' })
export class HighlightDirective { }
Property decorators:
@Input() title: string;
@Output() clicked = new EventEmitter<void>();
@ViewChild(ChildComponent) child: ChildComponent;
@HostBinding('class.active') isActive = false;
Method decorators:
@HostListener('click', ['$event'])
onClick(event: Event) { }
Parameter decorators:
constructor(@Inject(TOKEN) private config: Config) {}
constructor(@Optional() private logger: LoggerService) {}
Q. What is the difference between declarations, imports, providers and exports in NgModule?
The @NgModule decorator accepts a metadata object with key arrays that serve distinct purposes:
| Property |
Accepts |
Purpose |
declarations |
Components, Directives, Pipes |
Makes them available within this module's templates |
imports |
Other NgModules |
Imports the exported declarations of those modules into this module |
providers |
Services, Tokens |
Registers services with the module's injector |
exports |
Components, Directives, Pipes, Modules |
Makes them available to other modules that import this module |
bootstrap |
Components |
Root component(s) to insert into the DOM on startup |
@NgModule({
declarations: [
UserCardComponent, // belongs to THIS module
HighlightDirective,
TruncatePipe
],
imports: [
CommonModule, // provides *ngIf, *ngFor, async pipe etc.
ReactiveFormsModule // provides formGroup, formControl directives
],
providers: [
UserService // available to all components in this module
],
exports: [
UserCardComponent, // other modules importing this module can use this
HighlightDirective
]
})
export class UserModule {}
Q. What is Ivy in Angular?
Ivy is Angular's modern compilation and rendering engine, introduced as opt-in in Angular 8 and made the default engine in Angular 9.
Key improvements over the previous View Engine:
| Area |
View Engine |
Ivy |
| Bundle size |
Larger bundles |
Smaller bundles via better tree-shaking |
| Build speed |
Slower rebuilds |
Faster incremental compilation |
| Debugging |
Less informative stack traces |
Human-readable component debug info in DevTools |
| Type checking |
Limited template type-check |
Strict template type checking |
| Standalone components |
Not supported |
Fully supported (Angular 14+) |
Ivy powers modern Angular features:
- Standalone components (Angular 14+) — Components without
NgModule
- Typed reactive forms (Angular 14+)
- Required
@Input() (Angular 16+)
- Signals (Angular 17+)
// Standalone component (Ivy-powered, no NgModule needed)
@Component({
selector: 'app-hello',
standalone: true,
imports: [CommonModule],
template: `<p>Hello {{ name }}</p>`
})
export class HelloComponent {
name = 'Angular';
}
Q. What are the new features added in Angular 21?
Core Framework & Performance
- Zoneless by Default: New applications no longer include zone.js by default. This shift improves Core Web Vitals, reduces bundle size by approximately 30KB, and provides better control over change detection through signals.
- HttpClient Provided by Default: You no longer need to manually call provideHttpClient() in standalone applications; it is automatically provided at the root level.
- Vitest as Default Test Runner: Vitest has replaced Karma as the default testing framework for new projects, offering significantly faster execution and better compatibility with modern tooling.
- Generic SimpleChanges: The SimpleChanges type is now generic, allowing for stronger type checking of property values within the ngOnChanges lifecycle hook.
Reactive Forms & Templates
- Experimental Signal Forms: A new API built natively on Signals, designed to replace traditional Reactive and Template-driven forms with a more declarative, type-safe, and composable experience.
- NgStyle and NgClass Migrations: New schematics help automatically migrate NgStyle and NgClass directives to standard [style] and [class] bindings for better performance and readability.
- Enhanced Template Syntax:
- RegExp Support: Regular expressions can now be used directly within templates.
- Multiple Case Matching: The @switch control flow now supports fall-through cases, allowing multiple @case labels for a single block of code.
- Spread Operators: Templates now support spread operators (…) for array and object literals.
Developer Experience & AI
- Angular MCP Server: The CLI integrates a Model Context Protocol (MCP) server. It allows AI agents, such as GitHub Copilot or Gemini, to access up-to-date documentation, best practices, and project context.
- AI Tutor: An AI-powered learning assistant is included in the MCP server. It helps developers learn modern Angular concepts.
- Advanced Diagnostics: The compiler catches more errors at build time. For example, it can detect reading a required property before initialization.
Accessibility
- Angular Aria (Developer Preview): This is a new library of headless, accessible UI primitives. It includes components like Accordions, Menus, and Tabs. It handles complex accessibility patterns while allowing custom styles.
Q. What is angular CLI?
Angular CLI(Command Line Interface) is a command line interface to scaffold and build angular apps using nodejs style (commonJs) modules.
You need to install using below npm command,
npm install @angular/cli@latest
Below are the list of few commands, which will come handy while creating angular projects
1. Creating New Project ng new <project-name>
2. Generating Components, Directives & Services ng generate/g <feature-name>
The different types of commands would be,
- ng generate class my-new-class: add a class to your application
- ng generate component my-new-component: add a component to your application
- ng generate directive my-new-directive: add a directive to your application
- ng generate enum my-new-enum: add an enum to your application
- ng generate module my-new-module: add a module to your application
- ng generate pipe my-new-pipe: add a pipe to your application
- ng generate service my-new-service: add a service to your application
3. Running the Project ng serve
Q. What are the frequently used command in angular?
| Commands |
Description |
| ng new project-name |
Create an Angular project with Angular CLI |
| ng serve --open |
Builds and serves app, rebuilding on file changes |
| ng test |
Running unit tests |
| ng generate |
Generate Angular components |
| ng lint |
prints out linting errors |
| ng build |
Compiles an Angular app into an output directory named dist/ at the given output path. |
| ng build --prod |
apply uglify and minify to reduce the bundle as well make angular work in production mode which reduces runtime warnings given by angular compiler as well increase performance. The ng build command with the --prod meta-flag (ng build --prod) compiles with AOT by default. |
| ng doc |
Opens a browser window with the keyword as search in Angular documentation. |
ng test --watch=false --code-coverage |
Generate Code Coverage Reports |
| npm run |
Runs an Architect target with an optional custom builder configuration defined in project. |
| ng build --aot |
generally when we serve angular project all the angular files are downloaded on browser and it will compile and execute the application on the browser but in aot entire application delivered to the browser is precompiled hence improves the performance. |
| ng add @angular/pwa |
Adds support for an external library to project |
| ng generate web-worker app |
Add a Web Worker to angular app |
# 3. ARCHITECTURE
Q. How an Angular application gets started or loaded?
The main.ts file, that is the first code which gets executed. The job of main.ts is to bootstrap the application. It loads everything and controls the startup of the application.
main.ts:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
Most importantly here is the line where bootstraps start our angular app by passing app module to the method. AppModule refers to the app.module.ts file.
app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [ ],
bootstrap: [AppComponent]
})
export class AppModule { }
When angular starts, it bootstrap array in @NgModule. It basically there is a list of all components which should be known to Angular at the point of time it analyzes index.html file.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Angular 8</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<app-root>Loading...</app-root>
</body>
</html>
Q. What is difference between Angular JIT compilation and AOT compilation?
Angular has 2 types of build dev build or prod build
1. JIT:
Just-in-Time (JIT) is a type of compilation that compiles app in the browser at runtime. JIT compilation is the default when you run the ng build (build only) or ng serve (build and serve locally) CLI commands. i.e, the below commands used for JIT compilation,
ng build
ng serve
2. AOT:
Ahead-of-Time (AOT) is a type of compilation that compiles app at build time. For AOT compilation, include the --aot option with the ng build or ng serve command as below,
ng build --aot
ng serve --aot
ng build or ng build --dev - this is for development build
ng build --prod - this is for production build
| Dev Build |
Production build |
| Source maps(.js.map files) are generated |
Source maps not generated |
| Dev Build is not minified and uglified |
Production Build is minified and uglified |
| Dev build is not tree shaked |
Production build is tree shaked |
| No AOT compilation |
AOT compilation takes place |
- minification - process of removing excess whitespace, comments and optinal tokens like curly braces and semi colons
- uglification - process of transforming code to use short variable and function names
- tree shaking - is the process of removing any code that we are not actually using in our application from the final bundle
Note: The ng build command with the --prod meta-flag (ng build --prod) compiles with AOT by default.
Q. What are the advantages with AOT?
- Faster rendering The browser downloads a pre-compiled version of the application. So it can render the application immediately without compiling the app.
- Fewer asynchronous requests It inlines external HTML templates and CSS style sheets within the application javascript which eliminates separate ajax requests.
- Smaller Angular framework download size Does not require downloading the Angular compiler. Hence it dramatically reduces the application payload.
- Detect template errors earlier Detects and reports template binding errors during the build step itself
- Better security It compiles HTML templates and components into JavaScript. So there wont be any injection attacks.
Q. What are the ways to control AOT compilation?
You can control your app compilation in two ways
- By providing template compiler options in the
tsconfig.json file
- By configuring Angular metadata with decorators
Q. What are the three phases of AOT?
The AOT compiler works in three phases,
1. Code Analysis In this phase, the TypeScript compiler and AOT collector create a representation of the source.
2. Code Generation It handles the interpretation as well as places restrictions on what it interprets.
3. Template Type Checking In this phase, the Angular template compiler uses the TypeScript compiler to validate the binding expressions in templates.
Q. Can I use arrow functions in AOT?
No, Arrow functions or lambda functions can’t be used to assign values to the decorator properties. For example, the following snippet is invalid:
@Component({
providers: [{
provide: MyService, useFactory: () => getService()
}]
})
To fix this, it has to be changed as following exported function:
function getService(){
return new MyService();
}
@Component({
providers: [{
provide: MyService, useFactory: getService
}]
})
If you still use arrow function, it generates an error node in place of the function. When the compiler later interprets this node, it reports an error to turn the arrow function into an exported function.
Note: From Angular5 onwards, the compiler automatically performs this rewriting while emitting the .js file.
Q. How do you add web workers in your application?
We can add web worker anywhere in our application. For example, If the file that contains expensive computation is src/app/app.component.ts, we can add a Web Worker using ng generate web-worker app command which will create src/app/app.worker.ts web worker file. This command will perform below actions,
- Configure project to use Web Workers
- Adds app.worker.ts to receive messages
addEventListener('message', ({ data }) => {
const response = `worker response to ${data}`;
postMessage(response);
});
- The component
app.component.ts file updated with web worker file
if (typeof Worker !== 'undefined') {
// Create a new
const worker = new Worker('./app.worker', { type: 'module' });
worker.onmessage = ({ data }) => {
console.log('page got message: $\{data\}');
};
worker.postMessage('hello');
} else {
// Web Workers are not supported in this environment.
}
Note: You may need to refactor your initial scaffolding web worker code for sending messages to and from.
# 4. COMPONENT INTERACTION
Q. What are components in angular?
Components are the most basic UI building block of an Angular app which formed a tree of Angular components. These components are subset of directives. Unlike directives, components always have a template and only one component can be instantiated per an element in a template.
import { Component } from '@angular/core';
@Component ({
selector: 'my-app',
template: ` <div>
<h1>{{title}}</h1>
<div>Angular components example</div>
</div> `,
})
export class AppComponent {
title: string = 'Welcome to Angular world';
}
Q. What are directives in angular?
Directives add behaviour to an existing DOM element or an existing component instance.
There are four types of directives in Angular
- Components directives
- Structural directives
- Attribute directives
- Custom Directive
Structural Directives:
Structural Directives are directives which change the structure of the DOM by adding or removing elements. There are three built in structural directives, NgIf, NgFor and NgSwitch.
Example: Structural Directives
<div *ngIf="user$ | async as user">
<span>Name: {{user.name}}</span>
<span>Age: {{user.age}}</span>
</div>
Attribute Directives:
Attribute directives change the appearance or behavior of an element, component, or another directive. ngClass, ngStyle are examples of attribute directives built-in to the Angular framework.
Example: Attribute Directives
<p [ngStyle]="{'background': isBlue ? 'blue' : 'red'}"> I am an Attribute Directive</p>
Example: Custom Directive
import { Directive, ElementRef, Input } from '@angular/core';
@Directive({ selector: '[myHighlight]' })
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
Now this directive extends HTML element behavior with a yellow background as below
<p myHighlight>Highlight me!</p>
Q. What are the differences between Component and Directive?
A component is also a type of directive with template, styles and logic part.
| Component |
Directive |
| To register a component we use @Component meta-data annotation |
To register directives we use @Directive meta-data annotation |
| Components are typically used to create UI widgets |
Directive is used to add behavior to an existing DOM element |
| Component is used to break up the application into smaller components |
Directive is use to design re-usable components |
| Only one component can be present per DOM element |
Many directives can be used per DOM element |
| @View decorator or templateurl/template are mandatory |
Directive does not use View |
Example:
import { Component, HostListener, HostBinding, Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'red';
}
}
@Component({
selector: 'app-root',
template: `
<div *ngIf='myBool' appHighlight>Hi there</div>
`,
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
myBool:boolean = true;
}
Q. What is an Angular Module?
In Angular, a module is a mechanism to group components, directives, pipes and services that are related, in such a way that can be combined with other modules to create an application.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule ({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
The NgModule decorator has three options
- The imports option is used to import other dependent modules. The BrowserModule is required by default for any web based angular application
- The declarations option is used to define components in the respective module
- The bootstrap option tells Angular which Component to bootstrap in the application
Q. How to display only month in Angular?
import { Component } from '@angular/core';
@Component({
selector: 'app-birthday',
template: `<p>Birthday is {{ birthday | date:'LLLL'}}</p>` // January
})
export class BirthdayComponent {
birthday = new Date(2002, 1, 18);
}
Q. What is a bootstrapping module?
Every application has at least one Angular module, the root module that you bootstrap to launch the application is called as bootstrapping module. It is commonly known as AppModule. The default structure of AppModule generated by AngularCLI would be as follows,
/* JavaScript imports */
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
/* the AppModule class with the @NgModule decorator */
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Q. What are lifecycle hooks available in Angular?
Angular creates and renders components along with their children, checks when their data-bound properties change, and destroys them before removing them from the DOM.
Angular offers lifecycle hooks that provide visibility into these key life moments and the ability to act when they occur.
- ngOnChanges When the value of a data bound property changes, then this method is called.
- ngOnInit This is called whenever the initialization of the directive/component after Angular first displays the data-bound properties happens.
- ngDoCheck This is for the detection and to act on changes that Angular can not or wont detect on its own.
- ngAfterContentInit This is called in response after Angular projects external content into the components view.
- ngAfterContentChecked This is called in response after Angular checks the content projected into the component.
- ngAfterViewInit This is called in response after Angular initializes the components views and child views.
- ngAfterViewChecked This is called in response after Angular checks the components views and child views.
- ngOnDestroy This is the cleanup phase just before Angular destroys the directive/component.
Q. What is data binding in Angular?
Data binding is a core concept in Angular and allows to define communication between a component and the DOM, making it very easy to define interactive applications without worrying about pushing and pulling data.
From the Component to the DOM
1. Interpolation {{ value }}: Adds the value of a property from the component
<li>Name: {{ user.name }}</li>
<li>Address: {{ user.address }}</li>
2. Property binding [property] = "value": The value is passed from the component to the specified property or simple HTML attribute
<input type="email" [value]="user.email">
From the DOM to the Component:
3. Event binding (event) = "function": When a specific DOM event happens (eg.: click, change, keyup), call the specified method in the component
<button (click)="logout()"></button>
4. Two-way data binding [(ngModel)] = "value": Two-way data binding allows to have the data flow both ways. For example, in the below code snippet, both the email DOM input and component email property are in sync
<input type="email" [(ngModel)]="user.email">
Metadata is used to decorate a class so that it can configure the expected behavior of the class. The metadata is represented by decorators
1. Class Decorators e.g. @Component and @NgModule
import { NgModule, Component } from '@angular/core';
@Component({
selector: 'my-component',
template: '<div>Class decorator</div>',
})
export class MyComponent {
constructor() {
console.log('Hey I am a component!');
}
}
@NgModule({
imports: [],
declarations: [],
})
export class MyModule {
constructor() {
console.log('Hey I am a module!');
}
}
2. Property Decorators Used for properties inside classes, e.g. @Input() and @Output()
import { Component, Input } from '@angular/core';
@Component({
selector: 'my-component',
template: '<div>Property decorator</div>'
})
export class MyComponent {
@Input() title: string;
}
3. Method Decorators Used for methods inside classes, e.g. @HostListener()
import { Component, HostListener } from '@angular/core';
@Component({
selector: 'my-component',
template: '<div>Method decorator</div>'
})
export class MyComponent {
@HostListener('click', ['$event'])
onHostClick(event: Event) {
// clicked, `event` available
}
}
4. Parameter Decorators Used for parameters inside class constructors, e.g. @Inject()
import { Component, Inject } from '@angular/core';
import { MyService } from './my-service';
@Component({
selector: 'my-component',
template: '<div>Parameter decorator</div>'
})
export class MyComponent {
constructor(@Inject(MyService) myService) {
console.log(myService); // MyService
}
}
Q. What is the difference between constructor() and ngOnInit()?
TypeScript classes has a default method called constructor() which is normally used for the initialization purpose. Whereas ngOnInit() method is specific to Angular, especially used to define Angular bindings. Even though constructor() getting called first, it is preferred to use ngOnInit() method for Angular bindings.
Example
export class App implements OnInit{
constructor(){
//called first time before the ngOnInit()
}
ngOnInit(){
//called after the constructor and called after the first ngOnChanges()
}
}
Q. What is the purpose of ngFor directive?
NgFor is a structural directive, meaning that it changes the structure of the DOM. It is used to repeat a given HTML template once for each value in an array, each time passing it the array value as context for string interpolation or binding.
@Component({
selector: 'ngfor-app',
template: `
<ul>
<li *ngFor="let person of people">
{{ person.name }}
</li>
</ul>
`
})
class NgForAppComponent {
people: any[] = [
{ "name": "Douglas Pace" },
{ "name": "Mcleod Mueller" },
{ "name": "Day Meyers" }
];
}
Q. What happens if you use script tag inside template?
Angular recognizes the value as unsafe and automatically sanitizes it, which removes the <script> tag but keeps safe content such as the text content of the <script> tag. This way it eliminates the risk of script injection attacks.
Lets take an example of innerHtml property binding which causes XSS vulnerability,
export class InnerHtmlBindingComponent {
// For example, a user/attacker-controlled value from a URL.
htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
}
Q. What is Interpolation?
Interpolation is a special syntax that Angular converts into property binding. It is a convenient alternative to property binding. It is represented by double curly braces({{ }}). The text between the braces is often the name of a component property. Angular replaces that name with the string value of the corresponding component property.
<h3>
{{title}}
<img src="{{url}}" style="height:30px">
</h3>
In the example above, Angular evaluates the title and url properties and fills in the blanks, first displaying a bold application title and then a URL.
Q. What are template expressions?
A template expression produces a value similar to any Javascript expression. Angular executes the expression and assigns it to a property of a binding target; the target might be an HTML element, a component, or a directive. In the property binding, a template expression appears in quotes to the right of the = symbol as in [property]=“expression”.
In interpolation syntax, the template expression is surrounded by double curly braces. For example, in the below interpolation, the template expression is {{username}},
<h3>{{username}}, welcome to Angular</h3>
The below javascript expressions are prohibited in template expression
- assignments (=, +=, -=, …)
- new
- chaining expressions with ; or ,
- increment and decrement operators (++ and -)
Q. What are template statement?
A template statement responds to an event raised by a binding target such as an element, component, or directive. The template statement appear in quotes to the right of the = symbol like (event)=“statement”.
<button (click)="editProfile()">Edit Profile</button>
In the above expression, editProfile is a template statement. The below JavaScript syntax expressions are not allowed.
- new
- increment and decrement operators,
++ and --
- operator assignment, such as
+= and -=
- the bitwise operators
| and &
- the template expression operators
Q. What is the difference between Smart (Container) and Dumb (Presentational) Components?
Smart (Container) Components:
- Aware of the application state and logic
- Interact with services and state management
- Pass data down to child components via
@Input
- Listen to events from child components via
@Output
- Contain little to no template/UI logic
@Component({
selector: 'app-user-list-container',
template: `
<app-user-list
[users]="users$ | async"
(userSelected)="onUserSelected($event)">
</app-user-list>
`
})
export class UserListContainerComponent implements OnInit {
users$: Observable<User[]>;
constructor(private userService: UserService) {}
ngOnInit() {
this.users$ = this.userService.getUsers();
}
onUserSelected(user: User) {
// Handle business logic
}
}
Dumb (Presentational) Components:
- Not aware of application state
- Receive data only through
@Input
- Communicate only through
@Output events
- Are highly reusable and easily testable
- Focus solely on how things look
@Component({
selector: 'app-user-list',
template: `
<ul>
<li *ngFor="let user of users" (click)="selectUser(user)">
{{ user.name }}
</li>
</ul>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserListComponent {
@Input() users: User[];
@Output() userSelected = new EventEmitter<User>();
selectUser(user: User) {
this.userSelected.emit(user);
}
}
Q. How do you create nested components in Angular?
Nested components are components rendered inside another component's template. The parent passes data via @Input() and receives events via @Output().
Parent Component:
@Component({
selector: 'app-parent',
template: `
<h2>Parent Component</h2>
<app-child
[title]="parentTitle"
(notify)="onChildNotify($event)">
</app-child>
`
})
export class ParentComponent {
parentTitle = 'Data from Parent';
onChildNotify(message: string) {
console.log('Child says:', message);
}
}
Child Component:
@Component({
selector: 'app-child',
template: `
<h3>Child: {{ title }}</h3>
<button (click)="sendToParent()">Notify Parent</button>
`
})
export class ChildComponent {
@Input() title: string;
@Output() notify = new EventEmitter<string>();
sendToParent() {
this.notify.emit('Hello from child!');
}
}
Q. What is multi-slot content projection in Angular?
Multi-slot content projection allows a component to accept content in multiple named slots using the select attribute on <ng-content>.
@Component({
selector: 'app-card',
template: `
<div class="card">
<div class="card-header">
<ng-content select="[card-header]"></ng-content>
</div>
<div class="card-body">
<ng-content select="[card-body]"></ng-content>
</div>
<div class="card-footer">
<ng-content select="[card-footer]"></ng-content>
</div>
</div>
`
})
export class CardComponent {}
<app-card>
<div card-header>Card Title</div>
<p card-body>Card content goes here...</p>
<div card-footer>Footer actions</div>
</app-card>
# 6. PIPES
Q. What are pipes?
ToDo
Q. What is a parameterized pipe?
A pipe can accept any number of optional parameters to fine-tune its output. The parameterized pipe can be created by declaring the pipe name with a colon (:) and then the parameter value. If the pipe accepts multiple parameters, separate the values with colons. Lets take a birthday example with a particular format(dd/mm/yyyy)
import { Component } from '@angular/core';
@Component({
selector: 'app-birthday',
template: `<p>Birthday is {{ birthday | date:'dd/mm/yyyy'}}</p>` // 18/06/2002
})
export class BirthdayComponent {
birthday = new Date(2002, 6, 18);
}
Note: The parameter value can be any valid template expression, such as a string literal or a component property.
Q. What is a custom pipe?
A pipe is a class decorated with pipe metadata @Pipe() decorator, which you import from the core Angular library
@Pipe({name: 'myCustomPipe'})
The pipe class implements the PipeTransform() interface transform method that accepts an input value followed by optional parameters and returns the transformed value.
interface PipeTransform {
transform(value: any, ...args: any[]): any
}
The @Pipe() decorator allows to define the pipe name that you’ll use within template expressions. It must be a valid JavaScript identifier.
template: `{{someInputValue | myCustomPipe: someOtherValue}}`
Example:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'customFileSizePipe'})
export class FileSizePipe implements PipeTransform {
transform(size: number, extension: string = 'MB'): string {
return (size / (1024 * 1024)).toFixed(2) + extension;
}
}
Now you can use the above pipe in template expression as below,
template: `
<h2>Find the size of a file</h2>
<p>Size: {{288966 | customFileSizePipe: 'GB'}}</p>
`
Q. What is the difference between pure and impure pipe?
A pure pipe is only called when Angular detects a change in the value or the parameters passed to a pipe. For example, any changes to a primitive input value (String, Number, Boolean, Symbol) or a changed object reference (Date, Array, Function, Object). An impure pipe is called for every change detection cycle no matter whether the value or parameters changes. i.e, An impure pipe is called often, as often as every keystroke or mouse-move.
impure-pipe works for every change in the component
pure-pipe works only when the component is loaded.
@Pipe({
name: 'sort',
pure: false // true makes it pure and false makes it impure
})
export class myPipe implements PipeTransform {
transform(value: any, args?: any): any {
// your logic here and return the result
}
}
Q. What is the purpose of async pipe?
The AsyncPipe subscribes to an observable or promise and returns the latest value it has emitted. When a new value is emitted, the pipe marks the component to be checked for changes.
Lets take a time observable which continuously updates the view for every 2 seconds with the current time.
@Component({
selector: 'async-observable-pipe',
template: `<div><code>observable|async</code>:
Time: {{ time | async }}</div>`
})
export class AsyncObservablePipeComponent {
time = new Observable(observer =>
setInterval(() => observer.next(new Date().toString()), 2000)
);
}
Q. Explain on how to use HttpClient with an example?
Below are the steps need to be followed for the usage of HttpClient.
Step 01: Import HttpClient into root module
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
...
HttpClientModule
],
......
})
export class AppModule {}
Step 02: Inject the HttpClient into the application
Lets create a userProfileService(userprofile.service.ts) as an example. It also defines get method of HttpClient
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
const userProfileUrl: string = 'assets/data/profile.json';
@Injectable()
export class UserProfileService {
constructor(private http: HttpClient) { }
getUserProfile() {
return this.http.get(this.userProfileUrl);
}
}
Step 03: Create a component for subscribing service
Lets create a component called UserProfileComponent(userprofile.component.ts) which inject UserProfileService and invokes the service method,
fetchUserProfile() {
this.userProfileService.getUserProfile()
.subscribe((data: User) => this.user = {
id: data['userId'],
name: data['firstName'],
city: data['city']
});
}
Since the above service method returns an Observable which needs to be subscribed in the component.
Advantages:
- Contains testability features
- Provides typed request and response objects
- Intercept request and response
- Supports Observalbe APIs
- Supports streamlined error handling
Q. How can you read full response?
The response body may not return full response data because sometimes servers also return special headers or status code which which are important for the application workflow. In order to get full response, we should use observe option from HttpClient,
getUserResponse(): Observable<HttpResponse<User>> {
return this.HttpClient.get<User>(
this.userUrl, { observe: 'response' });
}
Now HttpClient.get() method returns an Observable of typed HttpResponse rather than just the JSON data.
If the request fails on the server or failed to reach the server due to network issues then HttpClient will return an error object instead of a successful reponse. In this case, we need to handle in the component by passing error object as a second callback to subscribe() method.
fetchUser() {
this.userService.getProfile()
.subscribe(
(data: User) => this.userProfile = { ...data }, // success path
error => this.error = error // error path
);
}
It is always a good idea to give the user some meaningful feedback instead of displaying the raw error object returned from HttpClient.
Q. How does async pipe prevents memory leaks?
The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes. When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.
# 7. RXJS
Q. What is RxJS?
RxJS is a library for composing asynchronous and callback-based code in a functional, reactive style using Observables. Many APIs such as HttpClient produce and consume RxJS Observables and also uses operators for processing observables.
For example, you can import observables and operators for using HttpClient as below,
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
Q. What is an RxJS Operator?
RxJS Operators are pure functions that transform information in the observable stream that create new observables, often based on the current observable.
The operators can be broken down in multiple categories. There are creation operators that create a new observable optionally from a source, such as a promise or a value, Transformation operators will transform the data in the stream, and filtration operators will act as a gate for the observable stream.
Categories of operators:
| AREA |
OPERATORS |
| Creation |
from,fromEvent, of |
| Combination |
combineLatest, concat, merge, startWith , withLatestFrom, zip |
| Filtering |
debounceTime, distinctUntilChanged, filter, take, takeUntil |
| Transformation |
bufferTime, concatMap, map, mergeMap, scan, switchMap |
| Utility |
tap |
| Multicasting |
share |
1. Pipeable Operators [pipe()]: These are operators that can be piped to existing Observables using the pipe syntax.
class PostsComponent {
private user: Observable<User>;
ngOnInit() {
this.posts = this.user.pipe(
map(user => user.id),
switchMap(id =>
this.postsService.getPosts(id)
)
);
}
}
2. Map Operator [map()]: The map() operator, basically, helps us to transform data using an observer. The map operator applies a given project function to each value emitted by the source Observable and emits the resulting values as an observable.
import {map} from 'rxjs/operators';
const nums = of (1, 2, 3);
const mulValues = map ((val: number) => val * 2);
const mulNums = mulValues (nums);
mulNums.subscribe(x => console.log(x));
// Outputs
// 1
// 4
// 6
3. Filter Operator [filter()]: RxJS filter() is used to filter values emitted by source Observable on the basis of given predicate. If the condition returns true, filter will emit value obtained from source Observable otherwise not.
Example: Filter values for null
this.countryName$ = this.filterDemoService.getCountry().pipe(
filter(country => country.getCountryName() !== null),
map(country => country.getCountryName()),
catchError(err => {
console.error(err);
return of("");
})
);
4. Concat Operator [concat()]: Creates an output Observable which sequentially emits all values from given Observable and then moves on to the next.
Example: Concatenate a timer counting from 0 to 3 with a synchronous sequence from 1 to 10
import { concat, interval, range } from 'rxjs';
import { take } from 'rxjs/operators';
const timer = interval(1000).pipe(take(4));
const sequence = range(1, 10);
const result = concat(timer, sequence);
result.subscribe(x => console.log(x));
// results in:
// 0 -1000ms-> 1 -1000ms-> 2 -1000ms-> 3 -immediate-> 1 ... 10
5. FlatMap Operator [flatMap()] or mergeMap Operator [mergeMap()]: flatMap() is an alias for mergeMap(). By using flatMap we can transform our event stream (the keypress events on the text field) into our response stream (the search results from the HTTP request).
Example: app/services/search.service.ts
import {Http} from '@angular/http';
import {Injectable} from '@angular/core';
@Injectable()
export class SearchService {
constructor(private http: Http) {}
search(term: string) {
return this.http
.get('https://api.spotify.com/v1/search?q=' + term + '&type=artist')
.map((response) => response.json())
}
}
app/app.component.ts
import { Component } from '@angular/core';
import { FormControl,
FormGroup,
FormBuilder } from '@angular/forms';
import { SearchService } from './services/search.service';
import 'rxjs/Rx';
@Component({
selector: 'app-root',
template: `
<form [formGroup]="coolForm"><input formControlName="search" placeholder="Search Spotify artist"></form>
<div *ngFor="let artist of result">
{{artist.name}}
</div>
`
})
export class AppComponent {
searchField: FormControl;
coolForm: FormGroup;
constructor(private searchService:SearchService, private fb:FormBuilder) {
this.searchField = new FormControl();
this.coolForm = fb.group({search: this.searchField});
this.searchField.valueChanges
.debounceTime(400)
.flatMap(term => this.searchService.search(term))
.subscribe((result) => {
this.result = result.artists.items
});
}
}
6. SwitchMap Operator [switchMap()]: The switchMap() operator switches from one stream to another, unsubscribing from the previous observable and returning a new observable.
import { Component } from '@angular/core';
import { FormControl, FormGroup, FormBuilder } from '@angular/forms';
import { SearchService } from './services/search.service';
import 'rxjs/Rx';
@Component({
selector: 'app-root',
template: `
<form [formGroup]="coolForm"><input formControlName="search" placeholder="Search Spotify artist"></form>
<div *ngFor="let artist of result">
{{artist.name}}
</div>
`
})
export class AppComponent {
searchField: FormControl;
coolForm: FormGroup;
constructor(private searchService:SearchService, private fb:FormBuilder) {
this.searchField = new FormControl();
this.coolForm = fb.group({search: this.searchField});
this.searchField.valueChanges
.debounceTime(400)
.switchMap(term => this.searchService.search(term))
.subscribe((result) => {
this.result = result.artists.items
});
}
}
7. Tap Operator [tap()]: The do() operator was renamed to tap() in RxJS v5.5.x as part of the upgrade to lettable operators to avoid a confict with the reserved word do (part of the do-while loop).
RxJS Tap operator uses to perform a side effect for every emission on the source Observable but returns an Observable that is identical to the source.
getProducts(): Observable<any[]> {
return this.http.get<any[]>(apiUrl)
.pipe(
tap(product => console.log('fetched products')),
catchError(this.handleError('getProducts', []))
);
}
8. Catch Operator [catch()]: The catch() operator was renamed in RxJS v5.5.x to catchError(). The catchError() operator to receive any error notifications that are emitted in the observable stream.
getProduct(id: number): Observable<any> {
const url = `${apiUrl}/${id}`;
return this.http.get<any>(url).pipe(
tap(_ => console.log(`fetched product id=${id}`)),
catchError(this.handleError<any>(`getProduct id=${id}`))
);
}
9. forkJoin Operator [forkJoin()]: The forkJoin() operator is similar to the Promise.all() method in that it starts (forks) multiple observers at once and then joins the final values from each observable when all observables complete. It is important to note that if any of the input observables never complete, then the forkJoin() will never complete.
Example: Multiple http calls in parallel using forkJoin()
Observable.forkJoin(
call1(params),
call2(params),
call3(params)
).subscribe((responses) => {
})
10. retry Operator [retry()]: retry() operator returns source Observable with the exception of an error. When source Observable calls error then retry operator resubscribe it for the maximum of given number of time. If Observable starts emitting elements and suppose at any point it calls error before completion, then retry operator will resubscribe the source Observable and starts emitting from start again.
return this.http
.get(this.url)
.retry(5);
11. StartWith Operator [startWith()]:
import { startWith } from 'rxjs/operators';
import { of } from 'rxjs';
//emit (1,2,3)
const source = of(1, 2, 3);
//start with 0
const example = source.pipe(startWith(0));
//output: 0,1,2,3
const subscribe = example.subscribe(val => console.log(val));
12. Of Operator [of()]:
import { of } from 'rxjs';
//emits any number of provided values in sequence
const source = of(1, 2, 3, 4, 5);
//output: 1,2,3,4,5
const subscribe = source.subscribe(val => console.log(val));
13. take Operator [take()]: take() an operator returns the first N values observed and complete stream. It is also another filteration operator.
import { interval } from ‘rxjs’;
import { take } from ‘rxjs/operators’;
const intervalCount = interval(1000);
const takeFive = intervalCount.pipe(take(5));
takeFive.subscribe(x => console.log(x));
Output
0, 1, 2, 3, 4
The above example will take only the first five elements after every 5 seconds with the 1-second interval for five seconds.
Q. What is rxjs subject in Angular?
An RxJS Subject is a special type of Observable that allows values to be multicasted to many Observers. While plain Observables are unicast (each subscribed Observer owns an independent execution of the Observable), Subjects are multicast.
A Subject observable is used to immediately notify subscribers of updated values emitted by it. It does not keep track of old values, i.e. if a Subject observable first emitted a value and was then later subscribed to, then the subscriber will not get that value. A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.
import { Subject } from 'rxjs';
const mySubject = new Rx.Subject();
mySubject.next(1); // Data can be pushed into the subject using its next method
const subscription1 = mySubject.subscribe(x => {
console.log('From subscription 1:', x);
});
mySubject.next(2);
const subscription2 = mySubject.subscribe(x => {
console.log('From subscription 2:', x);
});
mySubject.next(3);
subscription1.unsubscribe();
mySubject.next(4);
Output
From subscription 1: 2
From subscription 1: 3
From subscription 2: 3
</any></any></any></any></any></user></user></httpresponse></ng-content></string></user></user></script></script></feature-name></project-name></void></t></t></t>
> README 内容过长,已截取前 64 KB。完整内容请前往 GitHub 仓库查看。
评论