diff --git a/.github/workflows/jekyll-gh-pages.yml b/.github/workflows/jekyll-gh-pages.yml index 8d7c7590..263f0800 100644 --- a/.github/workflows/jekyll-gh-pages.yml +++ b/.github/workflows/jekyll-gh-pages.yml @@ -26,16 +26,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Pages - uses: actions/configure-pages@v2 + uses: actions/configure-pages@v5 - name: Build with Jekyll uses: actions/jekyll-build-pages@v1 with: source: ./ destination: ./_site - name: Upload artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v3 # Deployment job deploy: @@ -47,4 +47,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index b526d938..1b80a470 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,10 @@ * [Angular Animations](#-11-angular-animations) * [Performance](#-12-performance) * [Miscellaneous](#-13-miscellaneous) +* [Change Detection](#-14-change-detection) +* [Security](#-15-security) +* [Unit Testing](#-16-unit-testing) +* [Architecture Patterns](#-17-architecture-patterns)
@@ -46,55 +50,412 @@
+## 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 | + +
+ ↥ back to top +
+ +## 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 | + +
+ ↥ back to top +
+ ## Q. What is the difference between AngularJS and Angular? -Angular is a completely revived component-based framework in which an application is a tree of individual -components. +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 | -| AngularJS | Angular | -|---------------------------------------------------|-----------------------------------------------------| -|JavaScript-based framework for creating SPA. |Complete re-write of AngularJS version. | -|Still supported but no longer will be developed. |It is updated version regularly released because of Semantic Versioning.| -|The architecture of AngularJS is based on MVC. |The architecture of Angular 2 is component based| -|AngularJS was not developed with a mobile base in mind.|Angular 2 is a mobile-oriented framework.| -|AngularJS code can write by using only ES5, ES6, and Dart.|We can use ES5, ES6, Typescript to write an Angular 2 code.| -|Factory, service, provider, value and constant are used for services|The class is the only method to define services in Angular2| -|Run on only client-side |Runs on client-side & server-side| -|ng-app and angular bootstrap function are used to initialize | bootstrapmodule() function is used to initialize| +
+ ↥ back to top +
+ +## 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. + +```typescript +@NgModule({ + declarations: [AppComponent], // Components, Directives, Pipes + imports: [BrowserModule], // Other modules + providers: [UserService], // Services + bootstrap: [AppComponent] // Root component +}) +export class AppModule {} +``` -**a.) AngularJS:** +**2. Components** — The fundamental UI building block; each manages a view. -**Advantages:** +**3. Templates** — HTML with Angular-specific syntax for binding and directives. -* It has great MVC data binding that makes app development fast. -* Using HTML as a declarative language makes it very intuitive. -* It is a comprehensive solution for rapid front-end development since it does not need any other frameworks or plugins. -* AngularJS apps can run on every significant program and advanced cells including iOS and Android-based phones and tablets. -* Two-way data binding -* Directives -* Dependency injection +**4. Metadata / Decorators** — Decorators (`@Component`, `@NgModule`, etc.) provide Angular with configuration information. -**Disadvantages:** +**5. Data Binding** — Communication between the component class and its template. -* It is big and complicated due to the multiple ways of doing the same thing. -* Implementations scale poorly. -* If a user of an AngularJS application disables JavaScript, nothing but the basic page is visible. -* There is a lagging UI if there are more than 200 watchers. +**6. Directives** — Classes that add behaviour to DOM elements. -**b.) Angular:** +**7. Services** — Classes that encapsulate business logic, data access, and reusable functionality. -**Advantages:** +**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. + +
+ ↥ back to top +
+ +## 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. + +```typescript +// 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. + +```typescript +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. + +```typescript +getItems(url: string): Observable { + return this.http.get(url); +} +``` + +
+ ↥ back to top +
+ +## 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 | + +
+ ↥ back to top +
+ +## 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 `()`. + +```typescript +@Component({ + selector: 'app-root', + template: ` + +

Hello, {{ username }}!

+ ` +}) +export class AppComponent { + username = ''; +} +``` + +**Under the hood**, `[(ngModel)]` is shorthand for: + +```html + +``` + +**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 | + +
+ ↥ back to top +
+ +## 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:** + +1. **Angular Router** — Intercepts URL changes and renders the matching component without a full page reload. + +```typescript +const routes: Routes = [ + { path: '', component: HomeComponent }, + { path: 'about', component: AboutComponent }, + { path: 'users/:id', component: UserDetailComponent } +]; +``` + +2. **Component-based rendering** — Only the components that need to update are re-rendered. +3. **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 + +
+ ↥ back to top +
+ +## 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:** + +```typescript +@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:** + +```typescript +@Input() title: string; +@Output() clicked = new EventEmitter(); +@ViewChild(ChildComponent) child: ChildComponent; +@HostBinding('class.active') isActive = false; +``` + +**Method decorators:** + +```typescript +@HostListener('click', ['$event']) +onClick(event: Event) { } +``` + +**Parameter decorators:** + +```typescript +constructor(@Inject(TOKEN) private config: Config) {} +constructor(@Optional() private logger: LoggerService) {} +``` + +
+ ↥ back to top +
+ +## 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 | + +```typescript +@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 {} +``` + +
+ ↥ back to top +
+ +## 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+) | -* Component-based architecture that provides a higher quality of code -* Reusability: Components of similar nature are well encapsulated, in other words, self-sufficient. Developers can reuse them across different parts of an application. -* Unit-test friendly: The independent nature of components simplifies unit tests, quality assurance procedures aimed at verifying the performance of the smallest parts of the application, units. -* Maintainability: Components that are easily decoupled from each other can be easily replaced with better implementations. +**Ivy powers modern Angular features:** +- **Standalone components** (Angular 14+) — Components without `NgModule` +- **Typed reactive forms** (Angular 14+) +- **Required `@Input()`** (Angular 16+) +- **Signals** (Angular 17+) -**Disadvantages:** +```typescript +// Standalone component (Ivy-powered, no NgModule needed) +@Component({ + selector: 'app-hello', + standalone: true, + imports: [CommonModule], + template: `

Hello {{ name }}

` +}) +export class HelloComponent { + name = 'Angular'; +} +``` + +
+ ↥ back to top +
+ +## 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](https://vitest.dev/) 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 is verbose and complex -* Steep learning curve -* Migrating legacy systems from AngularJS to Angular requires time +* Angular MCP Server: The CLI integrates a [Model Context Protocol](https://modelcontextprotocol.io/introduction) (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.
↥ back to top @@ -141,21 +502,15 @@ The different types of commands would be, |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 e2e | Running end-to-end tests with protractor framwork | |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 build --dev | Compiles an Angular app into an output directory named dist/ at the given output path.| -|ng get/ng set | Set a value in the Angular CLI configuration | |ng doc | Opens a browser window with the keyword as search in Angular documentation. | -|ng eject | ejects your app and output the proper webpack configuration and scripts | -|ng xi18n | Extracts i18n messages from the templates. | |
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 xi18n --output-path src/locale |Internationalization | |ng generate web-worker app |Add a Web Worker to angular app|
@@ -347,85 +702,6 @@ If you still use arrow function, it generates an error node in place of the func ↥ back to top
-## Q. What is Angular Ivy? - -Angular Ivy is a new rendering engine for Angular. You can choose to opt in a preview version of Ivy from Angular version 8. - -1. You can enable ivy in a new project by using the --enable-ivy flag with the ng new command - -```js -ng new ivy-demo-app --enable-ivy -``` - -2. You can add it to an existing project by adding `enableIvy` option in the `angularCompilerOptions` in your project `tsconfig.app.json`. - -```typescript -{ - "compilerOptions": { ... }, - "angularCompilerOptions": { - "enableIvy": true - } -} -``` - - - -## Q. What are the features included in ivy preview? - -You can expect below features with Ivy preview, - -* Generated code that is easier to read and debug at runtime -* Faster re-build time -* Improved payload size -* Improved template type checking - - - -## Q. Can I use AOT compilation with Ivy? - -Yes, it is a recommended configuration. Also, AOT compilation with Ivy is faster. So you need set the default build options(with in angular.json) for your project to always use AOT compilation. - -```typescript -{ - "projects": { - "my-project": { - "architect": { - "build": { - "options": { - ... - "aot": true, - } - } - } - } - } -} -``` - - - -## Q. What is the purpose of metadata json files? - -The metadata.json file can be treated as a diagram of the overall structure of a decorator metadata, represented as an abstract syntax tree(AST). During the analysis phase, the AOT collector scan the metadata recorded in the Angular decorators and outputs metadata information in .metadata.json files, one per .d.ts file. - - - -## Q. Can I use any javascript feature for expression syntax in AOT? - -No, the AOT collector understands a subset of (or limited) JavaScript features. If an expression uses unsupported syntax, the collector writes an error node to the .metadata.json file. Later point of time, the compiler reports an error if it needs that piece of metadata to generate the application code. - - - ## 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, @@ -928,32 +1204,185 @@ In the above expression, editProfile is a template statement. The below JavaScri ↥ back to top
-## # 6. PIPES +## 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 -## Q. What are pipes? +```typescript +@Component({ + selector: 'app-user-list-container', + template: ` + + + ` +}) +export class UserListContainerComponent implements OnInit { + users$: Observable; -*ToDo* + constructor(private userService: UserService) {} - + ngOnInit() { + this.users$ = this.userService.getUsers(); + } -## Q. What is a parameterized pipe? + onUserSelected(user: User) { + // Handle business logic + } +} +``` -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) +**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 ```typescript -import { Component } from '@angular/core'; - @Component({ - selector: 'app-birthday', - template: `

Birthday is {{ birthday | date:'dd/mm/yyyy'}}

` // 18/06/2002 -}) -export class BirthdayComponent { - birthday = new Date(2002, 6, 18); -} + selector: 'app-user-list', + template: ` +
    +
  • + {{ user.name }} +
  • +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UserListComponent { + @Input() users: User[]; + @Output() userSelected = new EventEmitter(); + + 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:** + +```typescript +@Component({ + selector: 'app-parent', + template: ` +

Parent Component

+ + + ` +}) +export class ParentComponent { + parentTitle = 'Data from Parent'; + + onChildNotify(message: string) { + console.log('Child says:', message); + } +} +``` + +**Child Component:** + +```typescript +@Component({ + selector: 'app-child', + template: ` +

Child: {{ title }}

+ + ` +}) +export class ChildComponent { + @Input() title: string; + @Output() notify = new EventEmitter(); + + 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 ``. + +```typescript +@Component({ + selector: 'app-card', + template: ` +
+
+ +
+
+ +
+ +
+ ` +}) +export class CardComponent {} +``` + +```html + +
Card Title
+

Card content goes here...

+
Footer actions
+
+``` + + + +## # 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) + +```typescript +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-birthday', + template: `

Birthday is {{ birthday | date:'dd/mm/yyyy'}}

` // 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.* @@ -2109,19 +2538,6 @@ The commonly-needed services, pipes, and directives provided by `@angular/common ↥ back to top -## Q. What is codelyzer? - -Codelyzer provides set of tslint rules for static code analysis of Angular TypeScript projects. ou can run the static code analyzer over web apps, NativeScript, Ionic etc. Angular CLI has support for this and it can be use as below, - -```js -ng new codelyzer -ng lint -``` - - - ## # 11. ANGULAR ANIMATIONS
@@ -2613,57 +3029,103 @@ Basically you will see 3 main syntax in Angular DSL. ↥ back to top -## Q. What is Bazel tool? +## Q. What are the different types of providers in Angular? -Bazel is a powerful build tool developed and massively used by Google and it can keep track of the dependencies between different packages and build targets. In Angular8, you can build your CLI application with Bazel. +Angular\'s dependency injection supports several provider types: -*Note: The Angular framework itself is built with Bazel.* +**1. `useClass`**: Provide a different class for a given token. -**Advantages:** +```typescript +providers: [{ provide: LoggerService, useClass: ConsoleLoggerService }] +``` + +**2. `useValue`**: Provide a static value. + +```typescript +export const APP_CONFIG = { apiUrl: 'https://api.example.com' }; +providers: [{ provide: APP_CONFIG_TOKEN, useValue: APP_CONFIG }] +``` + +**3. `useExisting`**: Create an alias to another registered token. + +```typescript +providers: [{ provide: OldService, useExisting: NewService }] +``` -Below are the list of key advantages of Bazel tool, +**4. `useFactory`**: Use a factory function to create the instance at runtime. + +```typescript +export function loggerFactory(isDev: boolean) { + return isDev ? new DevLogger() : new ProdLogger(); +} -1. It creates the possibility of building your back-ends and front-ends with the same tool -2. The incremental build and tests -3. It creates the possibility to have remote builds and cache on a build farm. +providers: [{ + provide: LoggerService, + useFactory: loggerFactory, + deps: [IS_DEVELOPMENT] +}] +``` -## Q. How do you use Bazel with Angular CLI? +## Q. What is a factory provider and when should you use it? -The `@angular/bazel` package provides a builder that allows Angular CLI to use Bazel as the build tool. +A factory provider uses a factory function to create the dependency at runtime. It is useful when the service instance depends on runtime conditions or on other services/values. -**1. Use in an existing applciation:** Add `@angular/bazel` using CLI +```typescript +import { InjectionToken } from '@angular/core'; -```js -ng add @angular/bazel -``` +export const LOGGER = new InjectionToken('Logger'); -**2. Use in a new application:** Install the package and create the application with collection option +export function loggerFactory(http: HttpClient, config: AppConfig): Logger { + if (config.environment === 'production') { + return new RemoteLogger(http, config.loggingEndpoint); + } + return new ConsoleLogger(); +} -```js -npm install -g @angular/bazel -ng new --collection=@angular/bazel +@NgModule({ + providers: [{ + provide: LOGGER, + useFactory: loggerFactory, + deps: [HttpClient, AppConfig] + }] +}) +export class AppModule {} ``` -When you use ng build and ng serve commands, Bazel is used behind the scenes and outputs the results in dist/bin folder. - -## Q. How do you run Bazel directly? +## Q. What is hierarchical dependency injection in Angular? + +Angular\'s DI system is hierarchical — injectors mirror the component tree. When a component requests a dependency, Angular searches up the injector tree until it finds a matching provider. + +**Injector levels (top to bottom):** -Sometimes you may want to bypass the Angular CLI builder and run Bazel directly using Bazel CLI. You can install it globally using `@bazel/bazel` npm package. i.e, Bazel CLI is available under `@bazel/bazel` package. After you can apply the below common commands, +1. **NullInjector** — Throws an error if reached. +2. **Platform injector** — Platform-level services. +3. **Root module injector** — Services provided in `AppModule` or with `providedIn: 'root'`. +4. **Lazy module injector** — Services provided in lazy-loaded modules. +5. **Element injector** — Per-component providers declared in `@Component.providers`. -```javascrippt -bazel build [targets] // Compile the default output artifacts of the given targets. -bazel test [targets] // Run the tests with *_test targets found in the pattern. -bazel run [target]: Compile the program represented by target and then run it. +```typescript +// Creates a new instance scoped to this component and its children +@Component({ + selector: 'app-child', + template: `...`, + providers: [MyService] // component-level instance +}) +export class ChildComponent { + constructor(private myService: MyService) {} +} ``` +If `providers` is omitted on the component, the nearest ancestor injector\'s instance is used (singleton behaviour when provided at root). + @@ -2723,6 +3185,104 @@ Redux is a way to manage application state and improve maintainability of asynch ↥ back to top +## Q. What is ViewContainerRef in Angular? + +`ViewContainerRef` represents a container where one or more views can be attached dynamically. It provides methods to create, insert, move, and remove views (both component views and embedded views from `TemplateRef`). + +```typescript +@Component({ + selector: 'app-dynamic-host', + template: `` +}) +export class DynamicHostComponent implements OnInit { + @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef; + + constructor(private cfr: ComponentFactoryResolver) {} + + ngOnInit() { + this.loadComponent(); + } + + loadComponent() { + this.container.clear(); + // Angular 13+ simplified API + const componentRef = this.container.createComponent(AlertComponent); + componentRef.instance.message = 'Dynamically loaded!'; + } +} +``` + +**Common methods:** + +| Method | Description | +|--------|-------------| +| `createComponent(component)` | Creates and inserts a component view | +| `createEmbeddedView(templateRef, context?)` | Creates a view from a `TemplateRef` | +| `clear()` | Removes all views | +| `remove(index?)` | Removes a specific view | +| `move(viewRef, index)` | Moves a view to a new index | + + + +## Q. What is the difference between ViewChildren and ContentChildren? + +**`@ViewChildren`** queries multiple child elements defined inside the component\'s **own template**: + +```typescript +@Component({ + selector: 'app-parent', + template: ` + + ` +}) +export class ParentComponent implements AfterViewInit { + @ViewChildren(ItemComponent) itemComponents: QueryList; + + ngAfterViewInit() { + console.log(this.itemComponents.length); + // Listen for dynamic changes + this.itemComponents.changes.subscribe(() => { + console.log('Items changed!'); + }); + } +} +``` + +**`@ContentChildren`** queries multiple child elements **projected** into the component via ``: + +```typescript +@Component({ + selector: 'app-tabs', + template: `` +}) +export class TabsComponent implements AfterContentInit { + @ContentChildren(TabComponent) tabs: QueryList; + + ngAfterContentInit() { + this.tabs.forEach(tab => console.log(tab.label)); + } +} +``` + +```html + + Content 1 + Content 2 + +``` + +| | `@ViewChildren` | `@ContentChildren` | +|---|---|---| +| Source | Component\'s own template | Projected content via `ng-content` | +| Available in | `ngAfterViewInit` | `ngAfterContentInit` | +| Returns | `QueryList` | `QueryList` | + + + ## # 8. ROUTING
@@ -4081,72 +4641,276 @@ A Subject is like an Observable, but can multicast to many Observers. Subjects a ↥ back to top -## # 5. ANGULAR FORMS +## Q. How do you implement lazy loading in Angular? -
+Lazy loading defers the loading of a feature module until the route is first activated, reducing the initial bundle size and startup time. -## Q. What the importance of Dirty Flag, pristine, touched, untouched, valid, invalid? +**Step 1**: Create a feature module with its own routing: -* **Dirty flag** – indicates user has changed values -* **Pristine** – opposite of dirty flag -* **Touched** – indicates field is touched by user -* **Untouched** – Opposite of touched -* **Valid** – Checks whether all validation have passed -* **Invalid** – opposite of valid +```typescript +// users/users-routing.module.ts +const routes: Routes = [ + { path: '', component: UsersListComponent }, + { path: ':id', component: UserDetailComponent } +]; - +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class UsersRoutingModule {} +``` -## Q. What is defer in promise? +**Step 2**: Use `loadChildren` with a dynamic import in the root router: -`Defer` is a object that exposes promises. It has three methods. +```typescript +// app-routing.module.ts +const routes: Routes = [ + { + path: 'users', + loadChildren: () => import('./users/users.module').then(m => m.UsersModule) + }, + { path: '', redirectTo: '/home', pathMatch: 'full' } +]; +``` -* Reject -* Resolve -* Notify +**Preloading lazy modules** in the background after app start: + +```typescript +@NgModule({ + imports: [RouterModule.forRoot(routes, { + preloadingStrategy: PreloadAllModules + })] +}) +export class AppRoutingModule {} +``` -## Q. What is the difference between an Annotation and a Decorator in Angular? - -A decorator corresponds to a function that is called on the class whereas annotations are "only" metadata set on the class using the Reflect Metadata library. +## Q. What are route guards and what types are available in Angular? -With TypeScript and ES7, `@Something` is a decorator. In the context of Angular2, decorators like `@Component`, `@Injectable`, ... define metadata for the decorated element using the `Reflect.defineMetadata` method. +Route guards are interfaces that control whether navigation should proceed, be cancelled, or redirected. -|Annotation |Decorator | -|-------------------------|---------------------------| -|Used by Traceur compiler |Used by Typescript compiler| -|Annotation creates the attribute ‘annotations’ that stores arrays and pass metadata to the constructor of the annotated class. |It is a function that gets the object that needs to be decorated (or constructed). They can change the attributes of the object as necessary.| -|Annotations are hard-coded |Not hard-coded| -|Example – import {Component} from 'angular2/angular2';| Example - import {ComponentAnnotation as Component} from 'angular2/angular2';| +| Guard Interface | Usage | +|-----------------|-------| +| `CanActivate` | Prevent navigating to a route | +| `CanActivateChild` | Prevent navigating to child routes | +| `CanDeactivate` | Prevent navigating away from the current route | +| `CanLoad` | Prevent a lazy-loaded module from even being downloaded | +| `Resolve` | Pre-fetch data before activating a route | -Example: **Class decorator** +**Example: `CanActivate`** ```typescript -export function MyClassDecorator(value: string) { - return function (target: Function) { - Reflect.defineMetadata("MyClassDecorator", value, target); - } -} +@Injectable({ providedIn: 'root' }) +export class AuthGuard implements CanActivate { + constructor(private auth: AuthService, private router: Router) {} -@Component({ ... }) -@MyClassDecorator("my metadata") -export class AppComponent { - constructor() { - let decoratorValue: string - = Reflect.getMetadata("MyClassDecorator", this.constructor); + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { + if (this.auth.isLoggedIn()) { + return true; + } + this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } }); + return false; } } ``` - - -## Q. What is transclusion in angular? +```typescript +const routes: Routes = [ + { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] } +]; +``` + +**Example: `CanLoad`** (prevents lazy module from being downloaded) + +```typescript +@Injectable({ providedIn: 'root' }) +export class CanLoadGuard implements CanLoad { + constructor(private auth: AuthService) {} + + canLoad(): boolean { + return this.auth.isLoggedIn(); + } +} +``` + + + +## Q. What is a route resolver and how do you use it? + +A resolver pre-fetches data before a route is activated, ensuring the component always receives its required data on initialization. + +```typescript +@Injectable({ providedIn: 'root' }) +export class UserResolver implements Resolve { + constructor(private userService: UserService) {} + + resolve(route: ActivatedRouteSnapshot): Observable { + return this.userService.getUserById(route.params['id']); + } +} +``` + +Register in the route config: + +```typescript +const routes: Routes = [{ + path: 'users/:id', + component: UserDetailComponent, + resolve: { user: UserResolver } +}]; +``` + +Access the resolved data in the component: + +```typescript +export class UserDetailComponent implements OnInit { + user: User; + + constructor(private route: ActivatedRoute) {} + + ngOnInit() { + this.user = this.route.snapshot.data['user']; + // Or subscribe to handle future navigation changes: + this.route.data.subscribe(data => this.user = data['user']); + } +} +``` + + + +## Q. How do you implement HTTP caching and retry with interceptors? + +**Caching interceptor:** + +```typescript +@Injectable() +export class CacheInterceptor implements HttpInterceptor { + private cache = new Map>(); + + intercept(req: HttpRequest, next: HttpHandler): Observable> { + if (req.method !== 'GET') { + return next.handle(req); + } + const cached = this.cache.get(req.url); + if (cached) { + return of(cached.clone()); + } + return next.handle(req).pipe( + tap(event => { + if (event instanceof HttpResponse) { + this.cache.set(req.url, event.clone()); + } + }) + ); + } +} +``` + +**Retry interceptor:** + +```typescript +@Injectable() +export class RetryInterceptor implements HttpInterceptor { + intercept(req: HttpRequest, next: HttpHandler): Observable> { + return next.handle(req).pipe( + retryWhen(errors => + errors.pipe( + delayWhen(() => timer(1000)), + take(3) + ) + ) + ); + } +} +``` + +Register interceptors in `AppModule`: + +```typescript +providers: [ + { provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: RetryInterceptor, multi: true } +] +``` + + + +## # 5. ANGULAR FORMS + +
+ +## Q. What the importance of Dirty Flag, pristine, touched, untouched, valid, invalid? + +* **Dirty flag** – indicates user has changed values +* **Pristine** – opposite of dirty flag +* **Touched** – indicates field is touched by user +* **Untouched** – Opposite of touched +* **Valid** – Checks whether all validation have passed +* **Invalid** – opposite of valid + + + +## Q. What is defer in promise? + +`Defer` is a object that exposes promises. It has three methods. + +* Reject +* Resolve +* Notify + + + +## Q. What is the difference between an Annotation and a Decorator in Angular? + +A decorator corresponds to a function that is called on the class whereas annotations are "only" metadata set on the class using the Reflect Metadata library. + +With TypeScript and ES7, `@Something` is a decorator. In the context of Angular2, decorators like `@Component`, `@Injectable`, ... define metadata for the decorated element using the `Reflect.defineMetadata` method. + +|Annotation |Decorator | +|-------------------------|---------------------------| +|Used by Traceur compiler |Used by Typescript compiler| +|Annotation creates the attribute ‘annotations’ that stores arrays and pass metadata to the constructor of the annotated class. |It is a function that gets the object that needs to be decorated (or constructed). They can change the attributes of the object as necessary.| +|Annotations are hard-coded |Not hard-coded| +|Example – import {Component} from 'angular2/angular2';| Example - import {ComponentAnnotation as Component} from 'angular2/angular2';| + +Example: **Class decorator** + +```typescript +export function MyClassDecorator(value: string) { + return function (target: Function) { + Reflect.defineMetadata("MyClassDecorator", value, target); + } +} + +@Component({ ... }) +@MyClassDecorator("my metadata") +export class AppComponent { + constructor() { + let decoratorValue: string + = Reflect.getMetadata("MyClassDecorator", this.constructor); + } +} +``` + + + +## Q. What is transclusion in angular? Transclusion is a way to let you define a fixed view template, and at the same time allow you to define a slot for dynamic content by using `ng-content` tag. @@ -6142,122 +6906,372 @@ You should omit the brackets when all of the following are true ↥ back to top -## # 12. PERFORMANCE - -
- -## Q. How to optimize loading large data in angular? - -**Load Time Performance:** - -1. **AOT**: The Angular Ahead-of-Time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase before the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser. +## Q. What are Template-Driven Forms in Angular? -2. **Tree-shaking**: This is the process of removing unused code resulting in smaller build size. In **angular-cli**, Tree-Shaking is enabled by default. +Template-driven forms use `ngModel` and form directives in the template to implicitly build the form model. They are suitable for simple forms. -3. **Uglify**: It is the process where the code size is reduced using various code transformations like mangling, removal of white spaces, removal of comments etc. For webpack use uglify plugin and with angular-cli specify the “prod” flag to perform the uglification process. +**Step 1**: Import `FormsModule` -4. **Lazy loading**: Lazy loading is the mechanism where instead of loading complete app, we load only the modules which are required at the moment thereby reducing the initial load time. +```typescript +@NgModule({ imports: [FormsModule] }) +export class AppModule {} +``` -5. **Ivy Render Engine**: It results in much smaller bundle size than the current engine with improved debugging experience. +**Step 2**: Create the form template -6. **RxJS**: RxJS makes the whole library more tree-shakable thereby reducing the final bundle size. However, it has some breaking changes like operators chaining is not possible instead, pipe() function (helps in better tree shaking) is introduced to add operators. +```html +
+ +
+ Email is required + Invalid email format +
+ + +
+``` -7. **Service worker cache**: A service worker is a script that runs in the web browser and manages caching for an application. +```typescript +export class LoginComponent { + user = { email: '', password: '' }; -8. **defer attribute**: Mentioning defer attribute to script tag will defer the loading of the scripts (sychronous) until the document is not parsed thus making site interactive quicker. + onSubmit(form: NgForm) { + if (form.valid) { + console.log(form.value); + } + } +} +``` -9. **async attribute**: async delays the loading of scripts until the document is not parsed but without respecting the order of loading of the scripts. + -10. **ChangeDetectionStrategy.OnPush**: `ChangeDetectionStrategy.OnPush` tells Angular that the component only depends on his Inputs ( aka pure ) and needs to be checked in only the following cases: +## Q. What are Reactive Forms in Angular? -i). The `Input` reference changes. -ii). An event occurred from the component or one of his children. -iii). You run change detection explicitly by calling `detectChanges()/tick()/markForCheck()` +Reactive forms provide a model-driven approach where the form model is built explicitly in the component class, offering better control, testability, and scalability. -Example +**Step 1**: Import `ReactiveFormsModule` ```typescript -@Component({ - selector: 'my-select', - template: ` - ... - `, - changeDetection: ChangeDetectionStrategy.OnPush -}) +@NgModule({ imports: [ReactiveFormsModule] }) +export class AppModule {} ``` -11. **TrackBy:** If we provide a trackBy function, Angular can track which items have been added or removed according to the unique identifier and only create or destroy the things that have changed. - -Example: +**Step 2**: Build the form model using `FormBuilder` ```typescript -@Component({ - selector: 'my-app', - template: ` -
    -
  • {{item.id}}
  • -
- - `, -}) -export class App { +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; - constructor() { - this.collection = [{id: 1}, {id: 2}, {id: 3}]; - } - getItems() { - this.collection = this.getItemsFromServer(); - } - getItemsFromServer() { - return [{id: 1}, {id: 2}, {id: 3}, {id: 4}]; +export class SignupComponent implements OnInit { + signupForm: FormGroup; + + constructor(private fb: FormBuilder) {} + + ngOnInit() { + this.signupForm = this.fb.group({ + name: ['', [Validators.required, Validators.minLength(3)]], + email: ['', [Validators.required, Validators.email]], + password: ['', [Validators.required, Validators.minLength(8)]] + }); } - trackByFn(index, item) { - return index; // or item.id + + onSubmit() { + if (this.signupForm.valid) { + console.log(this.signupForm.value); + } } } ``` +**Step 3**: Bind in the template + +```html +
+ +
+ Name is required + Min 3 characters +
+ + + +
+``` + +| Feature | Template-Driven | Reactive | +|---------|-----------------|----------| +| Form model | Created by directives | Created in component class | +| Data flow | Asynchronous | Synchronous | +| Validation | Directives | Functions | +| Testability | Harder | Easier | +| Scalability | Simple forms | Complex/dynamic forms | + -## # 13. MISCELLANEOUS +## Q. How do you create custom validators in Angular? -
+**Synchronous custom validator (ValidatorFn):** -## Q. What are angular elements? +```typescript +import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; -Angular elements are Angular components packaged as **custom elements**(a web standard for defining new HTML elements in a framework-agnostic way). Angular Elements hosts an Angular component, providing a bridge between the data and logic defined in the component and standard DOM APIs, thus, providing a way to use Angular components in `non-Angular environments`. +export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + const forbidden = nameRe.test(control.value); + return forbidden ? { forbiddenName: { value: control.value } } : null; + }; +} - +// Usage +name: ['', [Validators.required, forbiddenNameValidator(/admin/i)]] +``` -## Q. What is the browser support of Angular Elements? +**Cross-field validator (group-level):** -Since Angular elements are packaged as custom elements the browser support of angular elements is same as custom elements support. This feature is is currently supported natively in a number of browsers and pending for other browsers. +```typescript +export function passwordMatchValidator(group: AbstractControl): ValidationErrors | null { + const pass = group.get('password')?.value; + const confirm = group.get('confirmPassword')?.value; + return pass === confirm ? null : { passwordMismatch: true }; +} -| Browser | Angular Element Support | -|---- | --------- | -| Chrome | Natively supported| -| Opera | Natively supported | -| Safari| Natively supported | -| Firefox | Natively supported from 63 version onwards. You need to enable dom.webcomponents.enabled and dom.webcomponents.customelements.enabled in older browsers | -| Edge| Currently it is in progress| +// Usage +this.fb.group({ + password: ['', Validators.required], + confirmPassword: ['', Validators.required] +}, { validators: passwordMatchValidator }) +``` - +**Async validator (e.g., check username availability):** -## Q. What are custom elements? +```typescript +export function uniqueUsernameValidator(userService: UserService): AsyncValidatorFn { + return (control: AbstractControl): Observable => { + return userService.checkUsername(control.value).pipe( + debounceTime(300), + map(isTaken => (isTaken ? { usernameTaken: true } : null)), + catchError(() => of(null)) + ); + }; +} -Custom elements (or Web Components) are a Web Platform feature which extends HTML by allowing you to define a tag whose content is created and controlled by JavaScript code. The browser maintains a `CustomElementRegistry` of defined custom elements, which maps an instantiable JavaScript class to an HTML tag. Currently this feature is supported by Chrome, Firefox, Opera, and Safari, and available in other browsers through polyfills. +// Usage +username: ['', Validators.required, uniqueUsernameValidator(this.userService)] +``` + +Display errors in template: + +```html +
+ This username is already taken. +
+``` -## Q. Do I need to bootstrap custom elements? +## Q. What are Dynamic Forms in Angular? + +Dynamic forms are built programmatically at runtime from a data model that describes the form structure. They are useful when the form fields are determined by backend data or user configuration. + +```typescript +// Question base data model +export class QuestionBase { + key: string; + label: string; + value: T; + validators: ValidatorFn[]; + controlType: string; + + constructor(options: Partial> = {}) { + this.key = options.key || ''; + this.label = options.label || ''; + this.value = options.value as T; + this.validators = options.validators || []; + this.controlType = options.controlType || 'textbox'; + } +} +``` + +```typescript +// Service to convert question array to FormGroup +@Injectable() +export class QuestionControlService { + toFormGroup(questions: QuestionBase[]): FormGroup { + const group: { [key: string]: FormControl } = {}; + questions.forEach(q => { + group[q.key] = new FormControl(q.value ?? '', q.validators); + }); + return new FormGroup(group); + } +} +``` + +```typescript +// Dynamic form component +@Component({ + selector: 'app-dynamic-form', + template: ` +
+
+ + +
+ +
+ ` +}) +export class DynamicFormComponent implements OnInit { + @Input() questions: QuestionBase[] = []; + form: FormGroup; + + constructor(private qcs: QuestionControlService) {} + + ngOnInit() { + this.form = this.qcs.toFormGroup(this.questions); + } + + onSubmit() { + console.log(this.form.value); + } +} +``` + + + +## # 12. PERFORMANCE + +
+ +## Q. How to optimize loading large data in angular? + +**Load Time Performance:** + +1. **AOT**: The Angular Ahead-of-Time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase before the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser. + +2. **Tree-shaking**: This is the process of removing unused code resulting in smaller build size. In **angular-cli**, Tree-Shaking is enabled by default. + +3. **Uglify**: It is the process where the code size is reduced using various code transformations like mangling, removal of white spaces, removal of comments etc. For webpack use uglify plugin and with angular-cli specify the “prod” flag to perform the uglification process. + +4. **Lazy loading**: Lazy loading is the mechanism where instead of loading complete app, we load only the modules which are required at the moment thereby reducing the initial load time. + +5. **Ivy Render Engine**: It results in much smaller bundle size than the current engine with improved debugging experience. + +6. **RxJS**: RxJS makes the whole library more tree-shakable thereby reducing the final bundle size. However, it has some breaking changes like operators chaining is not possible instead, pipe() function (helps in better tree shaking) is introduced to add operators. + +7. **Service worker cache**: A service worker is a script that runs in the web browser and manages caching for an application. + +8. **defer attribute**: Mentioning defer attribute to script tag will defer the loading of the scripts (sychronous) until the document is not parsed thus making site interactive quicker. + +9. **async attribute**: async delays the loading of scripts until the document is not parsed but without respecting the order of loading of the scripts. + +10. **ChangeDetectionStrategy.OnPush**: `ChangeDetectionStrategy.OnPush` tells Angular that the component only depends on his Inputs ( aka pure ) and needs to be checked in only the following cases: + +i). The `Input` reference changes. +ii). An event occurred from the component or one of his children. +iii). You run change detection explicitly by calling `detectChanges()/tick()/markForCheck()` + +Example + +```typescript +@Component({ + selector: 'my-select', + template: ` + ... + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +``` + +11. **TrackBy:** If we provide a trackBy function, Angular can track which items have been added or removed according to the unique identifier and only create or destroy the things that have changed. + +Example: + +```typescript +@Component({ + selector: 'my-app', + template: ` +
    +
  • {{item.id}}
  • +
+ + `, +}) +export class App { + + constructor() { + this.collection = [{id: 1}, {id: 2}, {id: 3}]; + } + getItems() { + this.collection = this.getItemsFromServer(); + } + getItemsFromServer() { + return [{id: 1}, {id: 2}, {id: 3}, {id: 4}]; + } + trackByFn(index, item) { + return index; // or item.id + } +} +``` + + + +## # 13. MISCELLANEOUS + +
+ +## Q. What are angular elements? + +Angular elements are Angular components packaged as **custom elements**(a web standard for defining new HTML elements in a framework-agnostic way). Angular Elements hosts an Angular component, providing a bridge between the data and logic defined in the component and standard DOM APIs, thus, providing a way to use Angular components in `non-Angular environments`. + + + +## Q. What is the browser support of Angular Elements? + +Since Angular elements are packaged as custom elements the browser support of angular elements is same as custom elements support. This feature is is currently supported natively in a number of browsers and pending for other browsers. + +| Browser | Angular Element Support | +|---- | --------- | +| Chrome | Natively supported| +| Opera | Natively supported | +| Safari| Natively supported | +| Firefox | Natively supported from 63 version onwards. You need to enable dom.webcomponents.enabled and dom.webcomponents.customelements.enabled in older browsers | +| Edge| Currently it is in progress| + + + +## Q. What are custom elements? + +Custom elements (or Web Components) are a Web Platform feature which extends HTML by allowing you to define a tag whose content is created and controlled by JavaScript code. The browser maintains a `CustomElementRegistry` of defined custom elements, which maps an instantiable JavaScript class to an HTML tag. Currently this feature is supported by Chrome, Firefox, Opera, and Safari, and available in other browsers through polyfills. + + + +## Q. Do I need to bootstrap custom elements? No, custom elements bootstrap (or start) automatically when they are added to the DOM, and are automatically destroyed when removed from the DOM. Once a custom element is added to the DOM for any page, it looks and behaves like any other HTML element, and does not require any special knowledge of Angular. @@ -6565,3 +7579,763 @@ Metadata rewriting is the process in which the compiler converts the expression + +## # 14. CHANGE DETECTION + +
+ +## Q. What is Change Detection in Angular? + +Change Detection is the mechanism by which Angular keeps the view in sync with the component data. Whenever data changes — due to user events, HTTP responses, timers, or Promises — Angular traverses the component tree to determine which views need to be re-rendered. + +**Angular uses Zone.js** to intercept all async operations (setTimeout, Promises, XHR, etc.) and automatically trigger change detection after each one completes. + +**Two Change Detection Strategies:** + +**1. Default (CheckAlways)** — Every component is checked on every change detection cycle regardless of whether its inputs changed. + +**2. OnPush** — A component is only checked when: +- An `@Input()` reference changes +- An event originates from the component or its children +- An `async` pipe emits a new value +- Change detection is triggered manually via `ChangeDetectorRef` + +```typescript +@Component({ + selector: 'app-user-card', + template: `

{{ user.name }}

`, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UserCardComponent { + @Input() user: User; +} +``` + + + +## Q. What is zone pollution in Angular and how do you prevent it? + +Zone pollution occurs when third-party code or non-Angular operations run inside Angular\'s zone, triggering unnecessary change detection cycles and degrading performance. + +**Common causes:** +- Third-party libraries using `setTimeout`, `setInterval`, or DOM event listeners +- Frequent scroll/resize event handlers not tied to UI updates +- Polling mechanisms that update internal state without changing the view + +**Solutions:** + +**1. Run code outside Angular\'s zone using `NgZone`:** + +```typescript +constructor(private ngZone: NgZone) {} + +ngOnInit() { + this.ngZone.runOutsideAngular(() => { + setInterval(() => { + this.updateInternalCounter(); // does not trigger CD + }, 100); + }); +} + +updateUI() { + this.ngZone.run(() => { + this.displayValue = this.internalCounter; // triggers CD + }); +} +``` + +**2. Use `ChangeDetectionStrategy.OnPush`** to limit change detection to components that actually changed. + +**3. Detach a component from the CD tree:** + +```typescript +constructor(private cdr: ChangeDetectorRef) { + this.cdr.detach(); +} + +updateView() { + this.cdr.detectChanges(); // manually trigger only when needed +} +``` + + + +## Q. How do you handle slow computations in Angular templates? + +Slow functions called directly in templates execute on every change detection cycle, causing performance degradation. + +**1. Use pure pipes instead of template methods:** + +❌ Avoid — method called on every CD cycle: +```html +
  • {{ formatItem(item) }}
  • +``` + +✅ Prefer — pure pipe is called only when input changes: +```typescript +@Pipe({ name: 'formatItem', pure: true }) +export class FormatItemPipe implements PipeTransform { + transform(item: Item): string { + return `${item.name} — $${item.price}`; + } +} +``` + +**2. Use `trackBy` in `*ngFor`** to prevent full list re-rendering: + +```html +
  • {{ item.name }}
  • +``` + +```typescript +trackById(index: number, item: Item): number { return item.id; } +``` + +**3. Memoize expensive computations:** + +```typescript +private _cache = new Map(); + +compute(input: string): any { + if (!this._cache.has(input)) { + this._cache.set(input, this.heavyComputation(input)); + } + return this._cache.get(input); +} +``` + + + +## Q. What are Angular lifecycle hooks and when are they called? + +| Hook | When It Is Called | +|------|------------------| +| `ngOnChanges(changes)` | Before `ngOnInit()` and whenever an `@Input()` property changes. Receives a `SimpleChanges` map. | +| `ngOnInit()` | Once, after the first `ngOnChanges()`. Use for component initialization. | +| `ngDoCheck()` | On every CD cycle. Use for custom change detection logic. | +| `ngAfterContentInit()` | Once, after projected content (`ng-content`) is initialized. | +| `ngAfterContentChecked()` | After every check of projected content. | +| `ngAfterViewInit()` | Once, after the component\'s view and child views are initialized. Use to access `@ViewChild`. | +| `ngAfterViewChecked()` | After every check of the component\'s view. | +| `ngOnDestroy()` | Just before Angular destroys the component. Use to unsubscribe and release resources. | + +```typescript +@Component({ selector: 'app-example', template: `

    {{ message }}

    ` }) +export class ExampleComponent implements OnInit, OnChanges, OnDestroy { + @Input() data: string; + private subscription: Subscription; + + ngOnChanges(changes: SimpleChanges) { + if (changes['data']) { + console.log('Changed:', changes['data'].previousValue, '→', changes['data'].currentValue); + } + } + + ngOnInit() { + this.subscription = someObservable$.subscribe(); + } + + ngOnDestroy() { + this.subscription.unsubscribe(); // Always clean up + } +} +``` + + + +## Q. What is NgZone and when should you use it? + +`NgZone` is an Angular service that wraps Zone.js and provides methods to execute code inside or outside Angular\'s change detection zone. + +**Key methods:** + +| Method | Purpose | +|--------|---------| +| `runOutsideAngular(fn)` | Run code without triggering change detection | +| `run(fn)` | Run code inside the zone (triggers CD) | +| `runGuarded(fn)` | Run inside zone with automatic error handling | +| `onStable` | Observable that emits after Angular finishes processing | + +```typescript +@Component({...}) +export class HeavyAnimationComponent { + constructor(private ngZone: NgZone) {} + + startAnimation() { + this.ngZone.runOutsideAngular(() => { + const animate = () => { + this.updateCanvasFrame(); // no CD triggered + requestAnimationFrame(animate); + }; + requestAnimationFrame(animate); + }); + } + + processResult(data: any) { + this.ngZone.run(() => { + this.result = data; // triggers CD to update view + }); + } +} +``` + + + +## # 15. SECURITY + +
    + +## Q. How does Angular prevent Cross-Site Scripting (XSS) attacks? + +Angular treats all values as untrusted by default and automatically sanitizes them before inserting into the DOM. + +**1. Template interpolation auto-escaping:** + +```html + +

    {{ userInput }}

    +``` + +**2. Property binding sanitization** — Angular sanitizes `[innerHTML]`, `[src]`, `[href]`, and `[style]`: + +```html +
    +``` + +**3. `DomSanitizer` for explicitly trusted content:** + +```typescript +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; + +@Component({ template: `
    ` }) +export class MyComponent { + trustedHtml: SafeHtml; + + constructor(private sanitizer: DomSanitizer) { + // ONLY use when you are 100% certain the content is safe + this.trustedHtml = this.sanitizer.bypassSecurityTrustHtml('Safe content'); + } +} +``` + +**Security contexts Angular enforces:** HTML, Style, URL, Resource URL, Script. + +**Best practices:** +- Never use `bypassSecurityTrust*` with user-controlled data +- Always validate and sanitize input on the server side +- Avoid direct DOM manipulation via `nativeElement`; use `Renderer2` instead +- Keep Angular and all dependencies updated + + + +## Q. What is Content Security Policy (CSP) and how does it work with Angular? + +CSP is an HTTP response header that restricts the resources the browser is allowed to load, mitigating XSS and injection attacks. + +**Example CSP header:** +``` +Content-Security-Policy: + default-src 'self'; + script-src 'self'; + style-src 'self' 'unsafe-inline'; + img-src 'self' data: https:; + connect-src 'self' https://api.example.com; +``` + +**Angular and CSP:** +- AOT-compiled Angular apps do not use `eval()`, making them compatible with strict CSP +- JIT compilation requires `'unsafe-eval'` — avoid JIT in production +- Angular-generated inline styles can be whitelisted with nonces (Angular 15+ supports `ng-csp`) + +```typescript +// In server.ts (Angular Universal / Express) +import * as crypto from 'crypto'; + +app.use((req, res, next) => { + const nonce = crypto.randomBytes(16).toString('base64'); + res.setHeader('Content-Security-Policy', + `script-src 'self' 'nonce-${nonce}'; style-src 'self' 'nonce-${nonce}'` + ); + next(); +}); +``` + + + +## Q. How do you prevent Cross-Site Request Forgery (CSRF) in Angular? + +Angular\'s `HttpClient` provides built-in CSRF protection by automatically reading a token from a cookie and attaching it as an HTTP header on mutating requests. + +```typescript +import { HttpClientXsrfModule } from '@angular/common/http'; + +@NgModule({ + imports: [ + HttpClientModule, + HttpClientXsrfModule.withOptions({ + cookieName: 'XSRF-TOKEN', // Cookie set by the server + headerName: 'X-XSRF-TOKEN' // Header Angular sends automatically + }) + ] +}) +export class AppModule {} +``` + +**Server side (Express.js):** + +```javascript +const csrf = require('csurf'); +app.use(csrf({ cookie: true })); +app.use((req, res, next) => { + res.cookie('XSRF-TOKEN', req.csrfToken()); + next(); +}); +``` + +**Additional Angular security best practices:** +- Use `HttpOnly` and `Secure` flags on session cookies +- Implement route guards for authentication and authorization +- Keep Angular and all dependencies updated (`npm audit`) +- Use HTTPS in production for all communication +- Avoid storing sensitive tokens in `localStorage` (prefer `HttpOnly` cookies) + + + +## # 16. UNIT TESTING + +
    + +## Q. How do you test an Angular component? + +Angular provides `TestBed` to create a testing module and `ComponentFixture` to interact with a component\'s template and class. + +```typescript +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { UserCardComponent } from './user-card.component'; + +describe('UserCardComponent', () => { + let component: UserCardComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserCardComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(UserCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); // triggers ngOnInit + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should display the user name', () => { + component.user = { name: 'Alice', email: 'alice@test.com' }; + fixture.detectChanges(); + const el = fixture.nativeElement as HTMLElement; + expect(el.querySelector('h2')?.textContent).toContain('Alice'); + }); + + it('should emit userSelected on button click', () => { + component.user = { name: 'Alice', email: 'alice@test.com' }; + fixture.detectChanges(); + spyOn(component.userSelected, 'emit'); + fixture.nativeElement.querySelector('button').click(); + expect(component.userSelected.emit).toHaveBeenCalledWith(component.user); + }); +}); +``` + + + +## Q. How do you test an Angular service with HTTP calls? + +Use `HttpClientTestingModule` and `HttpTestingController` to mock HTTP requests without making real network calls. + +```typescript +import { TestBed } from '@angular/core/testing'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { UserService } from './user.service'; + +describe('UserService', () => { + let service: UserService; + let httpMock: HttpTestingController; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [UserService] + }); + service = TestBed.inject(UserService); + httpMock = TestBed.inject(HttpTestingController); + }); + + afterEach(() => httpMock.verify()); // ensure no outstanding requests + + it('should fetch users', () => { + const mockUsers = [{ id: 1, name: 'Alice' }]; + + service.getUsers().subscribe(users => { + expect(users.length).toBe(1); + expect(users[0].name).toBe('Alice'); + }); + + const req = httpMock.expectOne('/api/users'); + expect(req.request.method).toBe('GET'); + req.flush(mockUsers); + }); +}); +``` + + + +## Q. How do you mock dependencies in Angular unit tests? + +**1. Spy on an existing service method:** + +```typescript +const userService = TestBed.inject(UserService); +spyOn(userService, 'getUsers').and.returnValue(of(mockUsers)); +``` + +**2. Provide a stub class:** + +```typescript +class MockUserService { + getUsers() { return of([{ id: 1, name: 'Mock User' }]); } +} + +TestBed.configureTestingModule({ + providers: [{ provide: UserService, useClass: MockUserService }] +}); +``` + +**3. Use `jasmine.createSpyObj`:** + +```typescript +const spy = jasmine.createSpyObj('UserService', ['getUsers', 'deleteUser']); +spy.getUsers.and.returnValue(of(mockUsers)); + +TestBed.configureTestingModule({ + providers: [{ provide: UserService, useValue: spy }] +}); +``` + + + +## Q. How do you test Angular directives and pipes? + +**Testing a directive:** + +```typescript +@Component({ template: `
    Test
    ` }) +class TestHostComponent {} + +describe('HighlightDirective', () => { + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent, HighlightDirective] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + }); + + it('should apply yellow background', () => { + const el = fixture.nativeElement.querySelector('div'); + expect(el.style.backgroundColor).toBe('yellow'); + }); +}); +``` + +**Testing a pure pipe (no TestBed needed):** + +```typescript +describe('TruncatePipe', () => { + let pipe: TruncatePipe; + + beforeEach(() => { pipe = new TruncatePipe(); }); + + it('should truncate long strings', () => { + expect(pipe.transform('Hello World', 5)).toBe('Hello...'); + }); + + it('should not truncate short strings', () => { + expect(pipe.transform('Hi', 10)).toBe('Hi'); + }); +}); +``` + + + +## Q. How do you generate and measure code coverage in Angular? + +**Generate coverage report:** + +```bash +ng test --no-watch --code-coverage +``` + +This generates a `coverage/` folder. Open `coverage/index.html` in a browser to view the full report. + +**Configure minimum coverage thresholds in `karma.conf.js`:** + +```javascript +coverageReporter: { + check: { + global: { + statements: 80, + branches: 70, + functions: 80, + lines: 80 + } + } +} +``` + +**Exclude files from coverage in `angular.json`:** + +```json +"codeCoverageExclude": [ + "src/app/models/**", + "src/environments/**" +] +``` + +| Metric | Meaning | +|--------|---------| +| **Statements** | % of code statements executed | +| **Branches** | % of conditional branches (if/else, ternary) executed | +| **Functions** | % of functions/methods called | +| **Lines** | % of source lines executed | + + + +## # 17. ARCHITECTURE PATTERNS + +
    + +## Q. What is a Monorepo and how do you use Nx with Angular? + +A monorepo is a single repository containing multiple related projects (applications and libraries). **Nx** is the leading tool for managing Angular monorepos, providing build optimisation, code sharing, and project-graph analysis. + +**Set up an Nx workspace:** + +```bash +npx create-nx-workspace my-org --preset=angular +``` + +**Typical structure:** + +``` +my-org/ + apps/ + shell/ # Host Angular application + dashboard/ # Feature application + libs/ + ui/ # Shared UI components + data-access/ # Services, API calls, state + feature-auth/ # Auth feature module + nx.json + tsconfig.base.json +``` + +**Generate a shared library:** + +```bash +nx generate @nrwl/angular:lib shared/ui +``` + +**Import across apps:** + +```typescript +import { ButtonComponent } from '@my-org/shared/ui'; +``` + +**Key Nx benefits:** + +| Feature | Benefit | +|---------|---------| +| Affected builds | Only rebuild changed projects: `nx affected:build` | +| Dependency graph | Visualise project deps: `nx graph` | +| Computation caching | Skip redundant work automatically | +| Code sharing | No need to publish internal npm packages | + + + +## Q. What are Microfrontends and how do you implement them in Angular? + +Microfrontends extend the microservices concept to the UI layer — each team owns and independently deploys a slice of the frontend. + +**Implementation approaches:** + +**1. Module Federation (Webpack 5) — recommended:** + +```bash +ng add @angular-architects/module-federation --project shell --port 4200 --type host +ng add @angular-architects/module-federation --project mfe1 --port 4201 --type remote +``` + +**Remote app `webpack.config.js`:** + +```javascript +module.exports = withModuleFederationPlugin({ + name: 'mfe1', + exposes: { + './Module': './src/app/flights/flights.module.ts', + }, +}); +``` + +**Shell app routing:** + +```typescript +{ + path: 'flights', + loadChildren: () => loadRemoteModule({ + type: 'module', + remoteEntry: 'http://localhost:4201/remoteEntry.js', + exposedModule: './Module' + }).then(m => m.FlightsModule) +} +``` + +**2. Angular Elements** — Export Angular components as Web Components, consumable in any framework. + +**3. iframes** — Simple isolation but with UX and performance drawbacks. + +| Benefit | Challenge | +|---------|-----------| +| Independent deployments | Shared dependency management | +| Team autonomy | Cross-MFE communication | +| Fault isolation | Consistent UX across teams | +| Smaller focused codebases | Potential bundle duplication | + + + +## Q. How does Angular Universal enable Server-Side Rendering (SSR)? + +Angular Universal renders Angular components on the server and sends pre-rendered HTML to the browser, improving First Contentful Paint (FCP), SEO, and performance on low-powered devices. + +**Add Universal to an existing app:** + +```bash +ng add @nguniversal/express-engine +``` + +**Build and serve:** + +```bash +npm run build:ssr +npm run serve:ssr +``` + +**Handle browser-only APIs** using platform checks: + +```typescript +import { PLATFORM_ID, Inject } from '@angular/core'; +import { isPlatformBrowser } from '@angular/common'; + +@Injectable() +export class StorageService { + constructor(@Inject(PLATFORM_ID) private platformId: Object) {} + + setItem(key: string, value: string) { + if (isPlatformBrowser(this.platformId)) { + localStorage.setItem(key, value); // Safe to call only in browser + } + } +} +``` + +**Avoid duplicate HTTP requests with `TransferState`:** + +```typescript +import { TransferState, makeStateKey } from '@angular/platform-browser'; + +const USERS_KEY = makeStateKey('users'); + +// On the server: store the response +this.state.set(USERS_KEY, users); + +// In the browser: retrieve without another HTTP call +const users = this.state.get(USERS_KEY, []); +``` + + + +## Q. What are Angular design patterns for large-scale applications? + +**1. Feature Module Pattern** — Organise code into cohesive feature modules (Auth, Dashboard, Reports). + +**2. Core / Shared / Feature Module Pattern:** +- `CoreModule` — Singleton services (auth, logging, error handling); imported once in `AppModule` +- `SharedModule` — Reusable components, directives, and pipes; imported in feature modules +- `FeatureModules` — Lazy-loaded, self-contained feature areas + +**3. Facade Pattern** — Abstract state management behind a simple service API: + +```typescript +@Injectable({ providedIn: 'root' }) +export class UserFacade { + users$ = this.store.select(selectAllUsers); + + constructor(private store: Store) {} + + loadUsers() { this.store.dispatch(loadUsers()); } + selectUser(id: number) { this.store.dispatch(selectUser({ id })); } +} +``` + +**4. Container / Presentational Pattern** — Smart components manage data and state; dumb components handle display only. + +**5. State Management with NgRx:** + +| Concept | Role | +|---------|------| +| `Actions` | Events describing state changes | +| `Reducers` | Pure functions producing new state | +| `Selectors` | Memoized state queries | +| `Effects` | Side effects (HTTP calls) handled in isolation | + +**6. OnPush + Immutability** — Use `ChangeDetectionStrategy.OnPush` with immutable data updates for optimal performance across large component trees. + + +