1. Core Concepts & Architecture
Q1: What is Angular and how does it differ from AngularJS?
Answer:
Angular (versions 2+) is a complete rewrite of AngularJS (version 1.x) with significant architectural differences:
Architecture: Angular uses component-based architecture while AngularJS used MVC
Language: Angular uses TypeScript as primary language, AngularJS used JavaScript
Mobile Support: Angular has built-in mobile support, AngularJS didn't
Performance: Angular is faster due to better change detection, Ahead-of-Time compilation
Dependency Injection: Angular has hierarchical DI, AngularJS had single DI system
Q2: Explain Angular's Architecture
Answer:
Angular follows a component-based architecture with these main building blocks:
Modules: Container for related components, services, directives (NgModule)
Components: Building blocks with view and logic
Templates: HTML views with Angular template syntax
Directives: Extend HTML with custom behavior
Services: Reusable business logic
Dependency Injection: Provides dependencies to classes
Q3: What are Angular Modules?
Answer:
Angular modules (NgModule) are containers that organize related code into functional sets:
@NgModule({ declarations: [AppComponent, UserComponent], // Components, Directives, Pipes imports: [BrowserModule, FormsModule], // Other modules providers: [UserService, AuthService], // Services bootstrap: [AppComponent] // Root component }) export class AppModule { }
Q4: What is TypeScript and why does Angular use it?
Answer:
TypeScript is a superset of JavaScript that adds static typing, classes, interfaces, and decorators. Angular uses it because:
Type Safety: Catches errors during development
Better Tooling: Enhanced IDE support with autocompletion
Modern Features: Classes, interfaces, generics
Decorators: Used for metadata (Component, Injectable, etc.)
Compatibility: Compiles to JavaScript for browser compatibility
Q5: Explain Angular's Change Detection
Answer:
Change detection is how Angular detects changes and updates the view:
Default Strategy: Checks all components on every event (ChangeDetectionStrategy.Default)
OnPush Strategy: Only checks when:
Input reference changes
Event is emitted from component
Async pipe receives new value
Manual trigger via ChangeDetectorRef
Zones: Monitors asynchronous operations to trigger change detection
Q6: What is Ahead-of-Time (AOT) compilation?
Answer:
AOT compilation compiles Angular templates during build time:
Benefits:
Faster rendering (no client-side compilation)
Smaller bundle size (no compiler in bundle)
Template errors caught early
Better security (no eval)
vs JIT: Just-in-Time compiles in browser, used mainly for development
2. Components & Templates
Q7: What is a Component in Angular?
Answer:
Components are the fundamental building blocks of Angular applications:
@Component({ selector: 'app-user', templateUrl: './user.component.html', styleUrls: ['./user.component.css'] }) export class UserComponent { @Input() user: User; @Output() userSelected = new EventEmitter<User>(); constructor() {} }
Q8: Explain Component Lifecycle Hooks
Answer:
Angular components have lifecycle hooks executed in this order:
ngOnChanges: When input properties change
ngOnInit: After first ngOnChanges (initialization logic)
ngDoCheck: During every change detection run
ngAfterContentInit: After content projection
ngAfterContentChecked: After checking projected content
ngAfterViewInit: After view initialization
ngAfterViewChecked: After checking component views
ngOnDestroy: Before component destruction (cleanup)
Q9: What is Data Binding in Angular?
Answer:
Data binding connects component data with the template:
Interpolation:
{{value}}- Component to DOMProperty Binding:
[property]="value"- Component to DOM propertyEvent Binding:
(event)="handler()"- DOM to componentTwo-way Binding:
[(ngModel)]="property"- Both waysAttribute Binding:
[attr.aria-label]="label"- For HTML attributesClass Binding:
[class.active]="isActive"- Dynamic classesStyle Binding:
[style.color]="textColor"- Dynamic styles
Q10: What are Template Reference Variables?
Answer:
Template reference variables (#var) reference DOM elements or directives:
<input #emailInput type="email"> <button (click)="validate(emailInput.value)">Validate</button>
Q11: Explain ViewChild and ViewChildren
Answer:
ViewChild: Accesses a single element/directive/component
@ViewChild('myInput') inputElement: ElementRef; @ViewChild(MyComponent) childComponent: MyComponent;
ViewChildren: Accesses multiple elements (QueryList)
@ViewChildren(MyComponent) childComponents: QueryList<MyComponent>;
Q12: What is Content Projection?
Answer:
Content projection (ng-content) projects external content into component:
<!-- Parent --> <app-card> <h1>Projected Content</h1> </app-card> <!-- Card Component --> <div class="card"> <ng-content></ng-content> </div>
Multi-slot projection:
<ng-content select="[header]"></ng-content> <ng-content select=".body"></ng-content>
3. Directives & Pipes
Q13: What are Directives?
Answer:
Directives add behavior to DOM elements:
Component Directives: Components with templates
Attribute Directives: Change appearance/behavior (ngClass, ngStyle)
Structural Directives: Change DOM layout (*ngIf, *ngFor, *ngSwitch)
Q14: Create a Custom Attribute Directive
Answer:
@Directive({ selector: '[appHighlight]' }) export class HighlightDirective { constructor(private el: ElementRef) {} @HostListener('mouseenter') onMouseEnter() { this.highlight('yellow'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(null); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; } }
Q15: Create a Custom Structural Directive
Answer:
@Directive({ selector: '[appUnless]' }) export class UnlessDirective { private hasView = false; constructor( private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef ) {} @Input() set appUnless(condition: boolean) { if (!condition && !this.hasView) { this.viewContainer.createEmbeddedView(this.templateRef); this.hasView = true; } else if (condition && this.hasView) { this.viewContainer.clear(); this.hasView = false; } } }
Q16: What are Pipes?
Answer:
Pipes transform data in templates:
Built-in pipes:
date,uppercase,lowercase,currency,percent,jsonCustom pipe:
@Pipe({ name: 'reverse' }) export class ReversePipe implements PipeTransform { transform(value: string): string { return value.split('').reverse().join(''); } }
Usage:
{{ 'hello' | reverse }}→ "olleh"
Q17: Pure vs Impure Pipes
Answer:
Pure pipes: Execute only when input value changes (default)
Impure pipes: Execute on every change detection cycle
@Pipe({ name: 'filter', pure: false // Makes it impure })
4. Services & Dependency Injection
Q18: What are Services?
Answer:
Services are singleton classes for shared business logic:
@Injectable({ providedIn: 'root' // Makes it tree-shakable }) export class DataService { private apiUrl = 'https://api.example.com'; constructor(private http: HttpClient) {} getData(): Observable<any> { return this.http.get(this.apiUrl); } }
Q19: Explain Dependency Injection in Angular
Answer:
DI is a design pattern where dependencies are provided rather than created:
Injectable Decorator: Marks class as injectable
Providers: Tell Angular how to create dependencies
Injector: Creates and manages dependencies
Hierarchy: Injectors form a tree matching component hierarchy
Q20: What are the different ways to provide services?
Answer:
Root level (Recommended):
@Injectable({ providedIn: 'root' })Module level:
providers: [MyService]in NgModuleComponent level:
providers: [MyService]in ComponentLazy-loaded module: Service instance specific to lazy module
Q21: What is @Injectable() decorator?
Answer:
Marks a class as available to injector for creation
Without it, Angular can't inject dependencies into the service
Required for services that have their own dependencies
Q22: How to inject a service?
Answer:
@Component({ selector: 'app-user', templateUrl: './user.component.html' }) export class UserComponent { // Injection via constructor constructor( private userService: UserService, @Inject('API_URL') private apiUrl: string ) {} }
5. Routing & Navigation
Q23: How to set up routing in Angular?
Answer:
const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'users', component: UserListComponent }, { path: 'users/:id', component: UserDetailComponent }, { path: '**', component: PageNotFoundComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Q24: What is RouterOutlet?
Answer:
RouterOutlet is a directive that marks where router should display components:
<router-outlet></router-outlet> <router-outlet name="sidebar"></router-outlet> <!-- Named outlet -->
Q25: How to navigate programmatically?
Answer:
export class UserComponent { constructor(private router: Router, private route: ActivatedRoute) {} goToUser(id: number) { // Navigate this.router.navigate(['/users', id]); // Navigate with relative path this.router.navigate(['../', id], { relativeTo: this.route }); // Navigate with query params this.router.navigate(['/users'], { queryParams: { page: 1 }, fragment: 'section1' }); } }
Q26: What are Route Guards?
Answer:
Route guards control navigation:
@Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate(): boolean { if (this.authService.isLoggedIn()) { return true; } this.router.navigate(['/login']); return false; } }
Types of guards:
CanActivate: Allow/deny access to routeCanActivateChild: Protect child routesCanDeactivate: Prevent leaving routeResolve: Pre-fetch data before activationCanLoad: Prevent lazy module loading
Q27: What is Lazy Loading?
Answer:
Lazy loading loads modules only when needed:
const routes: Routes = [ { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) } ];
Q28: How to pass data between routes?
Answer:
Multiple ways to pass data:
Route Parameters:
/users/:idQuery Parameters:
/users?page=1Route Data:
{ path: 'user', component: UserComponent, data: { role: 'admin' } }State:
this.router.navigate(['/user'], { state: { data: user } })
6. Forms (Reactive & Template-driven)
Q29: Reactive Forms vs Template-driven Forms
Answer:
Reactive Forms:
Created in component class
More control, easier testing
Scalable for complex forms
Immutable data flow
this.form = new FormGroup({ name: new FormControl('', Validators.required), email: new FormControl('', [Validators.required, Validators.email]) });
Template-driven Forms:
Created in template
Less code, simpler
Two-way binding
Good for simple forms
<input [(ngModel)]="user.name" name="name" required>
Q30: FormControl, FormGroup, FormArray
Answer:
FormControl: Tracks value/validity of single form control
FormGroup: Groups FormControls (for forms)
FormArray: Array of FormControls (for dynamic fields)
this.form = new FormGroup({ username: new FormControl(''), addresses: new FormArray([ new FormGroup({ street: new FormControl(''), city: new FormControl('') }) ]) });
Q31: Custom Validator
Answer:
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 this.form = new FormGroup({ name: new FormControl('', [ Validators.required, forbiddenNameValidator(/admin/i) ]) });
Q32: Cross-field Validation
Answer:
export const passwordMatchValidator: ValidatorFn = ( formGroup: FormGroup ): ValidationErrors | null => { const password = formGroup.get('password'); const confirmPassword = formGroup.get('confirmPassword'); return password && confirmPassword && password.value !== confirmPassword.value ? { passwordMismatch: true } : null; }; // Apply to form group this.form = new FormGroup({ password: new FormControl(''), confirmPassword: new FormControl('') }, { validators: passwordMatchValidator });
7. State Management
Q33: What is NgRx?
Answer:
NgRx is Redux pattern implementation for Angular:
Store: Single source of truth
Actions: Describe events
Reducers: Pure functions handling state changes
Selectors: Get slices of state
Effects: Handle side effects
Q34: Services vs NgRx for State Management
Answer:
Services: Simple apps, less boilerplate, easier learning curve
NgRx: Complex apps, predictable state, debugging (Redux DevTools), standardized patterns
Q35: What are Subjects in RxJS?
Answer:
Subjects are both Observable and Observer:
Subject: No initial value, multicasts to subscribers
BehaviorSubject: Has initial value, emits current value to new subscribers
ReplaySubject: Replays specified number of emissions
AsyncSubject: Emits only last value on completion
private dataSubject = new BehaviorSubject<string>('initial'); public data$ = this.dataSubject.asObservable(); updateData(newData: string) { this.dataSubject.next(newData); }
8. RxJS & Observables
Q36: Observable vs Promise
Answer:
Observable:
Lazy (executes when subscribed)
Multiple values over time
Cancellable (unsubscribe)
Operators for transformation
Better for event streams
Promise:
Eager (executes immediately)
Single value
Not cancellable
Simpler API
Q37: Common RxJS Operators
Answer:
Creation:
of,from,interval,timerTransformation:
map,switchMap,mergeMap,concatMapFiltering:
filter,take,debounceTime,distinctUntilChangedCombination:
combineLatest,forkJoin,mergeError Handling:
catchError,retry
Q38: What is switchMap?
Answer:
switchMap cancels previous inner observable when new outer value arrives:
searchTerm$.pipe( debounceTime(300), switchMap(term => this.http.get(`/api/search?q=${term}`)) );
Ideal for search inputs where only latest search matters.
Q39: How to prevent memory leaks?
Answer:
Always unsubscribe from observables:
// Manual private subscription: Subscription; this.subscription = observable$.subscribe(); ngOnDestroy() { this.subscription.unsubscribe(); } // Using takeUntil private destroy$ = new Subject<void>(); observable$.pipe(takeUntil(this.destroy$)).subscribe(); ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } // Async pipe (automatic) data$ = this.service.getData(); // In template: {{ data$ | async }}
9. HTTP Client & APIs
Q40: How to use HttpClient?
Answer:
@Injectable({ providedIn: 'root' }) export class ApiService { constructor(private http: HttpClient) {} getUsers(): Observable<User[]> { return this.http.get<User[]>('/api/users'); } createUser(user: User): Observable<User> { return this.http.post<User>('/api/users', user); } updateUser(id: number, user: User): Observable<User> { return this.http.put<User>(`/api/users/${id}`, user); } deleteUser(id: number): Observable<void> { return this.http.delete<void>(`/api/users/${id}`); } }
Q41: HTTP Interceptors
Answer:
Interceptors transform HTTP requests/responses:
@Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const token = localStorage.getItem('token'); if (token) { const cloned = req.clone({ headers: req.headers.set('Authorization', `Bearer ${token}`) }); return next.handle(cloned); } return next.handle(req); } } // Provide in module providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ]
Q42: Error Handling in HTTP
Answer:
getData(): Observable<Data> { return this.http.get<Data>('/api/data').pipe( catchError((error: HttpErrorResponse) => { if (error.status === 404) { return of([]); // Return fallback } return throwError(() => new Error('Something went wrong')); }), retry(3) // Retry on failure ); }
10. Performance Optimization
Q43: How to optimize Angular app performance?
Answer:
Use OnPush Change Detection
Lazy load modules
*TrackBy in ngFor
<div *ngFor="let item of items; trackBy: trackById">trackById(index: number, item: any): number { return item.id; }
Unsubscribe from observables
Use pure pipes
Virtual scrolling for large lists
AOT compilation
Tree shaking
Compress assets
Implement caching
Q44: What is Angular Ivy?
Answer:
Ivy is Angular's rendering engine since v9:
Smaller bundle sizes
Faster compilation
Better debugging
Improved type checking
Backward compatible
Q45: How to implement lazy loading images?
Answer:
@Directive({ selector: 'img[appLazyLoad]' }) export class LazyLoadImageDirective { @Input() src: string; constructor(private el: ElementRef) {} ngOnInit() { const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { this.el.nativeElement.src = this.src; observer.unobserve(this.el.nativeElement); } }); }); observer.observe(this.el.nativeElement); } }
11. Testing
Q46: Testing Components with TestBed
Answer:
describe('UserComponent', () => { let component: UserComponent; let fixture: ComponentFixture<UserComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [UserComponent], imports: [FormsModule], providers: [UserService] }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(UserComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); it('should display user name', () => { component.user = { name: 'John' }; fixture.detectChanges(); const element = fixture.nativeElement.querySelector('.user-name'); expect(element.textContent).toContain('John'); }); });
Q47: Testing Services
Answer:
describe('DataService', () => { let service: DataService; let httpTestingController: HttpTestingController; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [DataService] }); service = TestBed.inject(DataService); httpTestingController = TestBed.inject(HttpTestingController); }); afterEach(() => { httpTestingController.verify(); }); it('should get users', () => { const mockUsers = [{ id: 1, name: 'John' }]; service.getUsers().subscribe(users => { expect(users).toEqual(mockUsers); }); const req = httpTestingController.expectOne('/api/users'); expect(req.request.method).toBe('GET'); req.flush(mockUsers); }); });
12. Advanced Topics
Q48: What is Angular Elements?
Answer:
Angular Elements package Angular components as custom elements (web components):
Use outside Angular apps
Framework agnostic
Self-bootstrapping
@NgModule({ declarations: [CustomButtonComponent], imports: [BrowserModule], entryComponents: [CustomButtonComponent] }) export class AppModule { constructor(injector: Injector) { const customElement = createCustomElement(CustomButtonComponent, { injector }); customElements.define('custom-button', customElement); } }
Q49: Server-Side Rendering (SSR) with Angular Universal
Answer:
SSR renders app on server for:
Better SEO
Faster initial load
Social media previews
Setup:
ng add @nguniversal/express-engineQ50: Progressive Web Apps (PWA) with Angular
Answer:
Angular PWA features:
ng add @angular/pwaService Workers: Offline capability
Web App Manifest: Installable
Cache strategies
Push notifications
Q51: Micro Frontends with Angular
Answer:
Micro frontends in Angular can be implemented using:
Web Components (Angular Elements)
Module Federation (Webpack 5)
Single-spa framework
Nx workspace for monorepo
Q52: Signal-Based Components (Angular 16+)
Answer:
Signals provide fine-grained reactivity:
@Component({ template: `Count: {{ count() }}`, changeDetection: ChangeDetectionStrategy.OnPush }) export class CounterComponent { count = signal(0); doubleCount = computed(() => this.count() * 2); increment() { this.count.update(value => value + 1); } }
13. Angular 2026 Updates & Best Practices
Q53: What's new in Angular 2025/2026?
Answer:
Latest features include:
Standalone Components by default (less NgModules)
Enhanced Signals API
Improved hydration for SSR
Better build performance with esbuild
Enhanced DevTools
Strict typing improvements
Better bundle analysis tools
Q54: Standalone Components
Answer:
Standalone components don't need NgModule:
@Component({ selector: 'app-standalone', standalone: true, // Mark as standalone imports: [CommonModule, FormsModule], // Import directly template: `...` }) export class StandaloneComponent { }
Q55: Best Practices for 2026
Answer:
Use standalone components when possible
Implement Signals for reactive state
Use inject() function for dependency injection
Follow strict typing
Implement error boundaries
Use functional guards/interceptors
Optimize bundle with lazy loading
Implement proper error handling
Write comprehensive tests
Monitor performance with Core Web Vitals
Q56: Common Mistakes to Avoid
Answer:
Not unsubscribing from observables
Using ngIf with async pipe without alias
<!-- Bad --> <div *ngIf="data$ | async"> {{ (data$ | async).name }} </div> <!-- Good --> <div *ngIf="data$ | async as data"> {{ data.name }} </div>
Memory leaks with event listeners
Overusing change detection
Ignoring OnPush strategy
Not optimizing bundle size
Poor error handling
Not testing edge cases
Q57: Angular Interview Coding Challenges
Answer:
Challenge 1: Create a debounce search
@Component({ selector: 'app-search', template: ` <input (input)="onSearch($event.target.value)" /> <div *ngFor="let result of results$ | async">{{ result }}</div> ` }) export class SearchComponent { private searchSubject = new Subject<string>(); results$ = this.searchSubject.pipe( debounceTime(300), distinctUntilChanged(), switchMap(term => this.searchService.search(term)) ); onSearch(term: string) { this.searchSubject.next(term); } }
Challenge 2: Infinite scroll
@Directive({ selector: '[appInfiniteScroll]' }) export class InfiniteScrollDirective { @Output() scrolled = new EventEmitter(); constructor(private element: ElementRef) {} @HostListener('scroll') onScroll() { const element = this.element.nativeElement; const atBottom = element.scrollHeight - element.scrollTop <= element.clientHeight + 50; if (atBottom) { this.scrolled.emit(); } } }
Conclusion
Mastering Angular requires understanding both fundamental concepts and staying updated with the latest features. For 2026 interviews, focus on:
Core concepts (Components, Directives, Services, DI)
Modern features (Signals, Standalone Components)
Performance optimization techniques
State management strategies
Testing methodologies
Latest updates in Angular ecosystem
Preparation Tips:
Build real projects to understand concepts practically
Contribute to open-source Angular projects
Follow Angular blog and RFCs for updates
Practice coding challenges
Understand not just "how" but "why" behind features