Angular Practical Flashcards
These advanced questions cover real-world scenarios and libraries you may encounter when building or scaling Angular applications. They will help you demonstrate practical knowledge and experience during interviews.
What libraries do you use for state management in Angular, and how do they work?
In Angular, popular libraries for state management include:
NgRx:
It implements the Redux pattern, using actions, reducers, selectors, and effects to manage the application state in a predictable way. It centralizes state, allowing components to easily access and update it.
Akita:
A less complex state management library that focuses on maintaining a simple store structure with entities and active entities for better performance and easier API management.
NgXs:
A state management library that is simpler than NgRx, using decorators and plain TypeScript classes for actions and state. It integrates well with Angular’s DI and is less boilerplate-heavy.
// Example of using NgRx:
this.store.dispatch(new AddItem({ id: 1, name: ‘Item’ }));
this.store.select(‘items’).subscribe(items => console.log(items));
How do you handle API requests and error management in large Angular applications?
In larger applications, managing API requests and errors requires a robust approach:
- Interceptor: Use HttpInterceptor to centralize error handling and log requests/responses globally.
- Service-based architecture: Use Angular services for making API requests and managing business logic.
- Retry mechanism: Use RxJS operators like retry and catchError to handle failed requests.
- Global error handling: Implement a global error handler using ErrorHandler to log and display errors in a consistent manner.
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((error) => {
console.error('Error occurred:', error);
return throwError(error);
})
);
}
}</any></any>
Which Angular UI component libraries can be used in projects?
There are several UI libraries that can be used in Angular projects:
Angular Material: A comprehensive set of pre-built components following Material Design guidelines, providing responsive UI components like buttons, cards, dialog boxes, and tables.
PrimeNG: Another powerful UI library offering a wide range of customizable components, such as data tables, charts, form elements, and more.
NG Bootstrap: A UI library that brings the full power of Bootstrap into Angular using native Angular directives.
Ant Design for Angular: A UI library based on Ant Design, offering components with a clean, minimalist design.
<mat-table [dataSource]=”data”>
<ng-container>
<th mat-header-cell *matHeaderCellDef> Position </th>
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>
</mat-table>
How do you optimise performance in large-scale Angular applications?
To optimise performance in large Angular applications:
- Lazy loading: Implement lazy loading for feature modules, loading them only when necessary.
- OnPush change detection strategy: Use the OnPush change detection strategy to reduce the number of change detection cycles.
- AOT (Ahead-of-Time) compilation: Use AOT to compile the application during the build process for faster rendering and smaller bundle sizes.
- TrackBy with ngFor: Use trackBy with ngFor to improve performance by only updating changed items in a list.
- Bundle optimisation: Use Angular’s ng build –prod with optimisations such as tree-shaking, dead code elimination, and minification.
// Using OnPush Change Detection Strategy:
@Component({
selector: ‘app-example’,
changeDetection: ChangeDetectionStrategy.OnPush,
template: <p>{{ data }}</p>
,
})
export class ExampleComponent { }
How do you implement internationalisation (i18n) in Angular?
Internationalisation (i18n) in Angular can be achieved using Angular’s built-in i18n tools or third-party libraries like ngx-translate.
- Built-in i18n: Angular’s official support for localisation uses message extraction (ng extract-i18n), translation files, and a runtime loader for managing different languages.
- ngx-translate: This third-party library provides more flexibility by loading translations dynamically and supporting features like fallback languages and parameterised strings.
// Using ngx-translate
this.translateService.use(‘en’);
<p>{{ 'HELLO' | translate }}</p>
How would you implement form validation in a real-world Angular application?
Form validation can be handled in two ways:
Template-driven forms:
Validation is done using Angular directives like required, minlength, and pattern.
Reactive forms:
Validation logic is handled programmatically using FormControl and FormGroup, allowing for more flexibility, including custom validators and cross-field validation.
// Example of reactive form validation
this.form = this.fb.group({
email: [’’, [Validators.required, Validators.email]],
password: [’’, Validators.required],
});
How do you implement real-time updates in Angular using WebSockets or RxJS?
For real-time data, Angular applications can use WebSockets or server-sent events (SSE) with RxJS to manage live updates.
WebSockets: Use the native WebSocket API or libraries like ngx-socket-io to handle real-time communication between client and server.
RxJS: Combine WebSockets with RxJS to handle streams of real-time data efficiently.
const socket = new WebSocket(‘ws://example.com/socket’);
const messages = fromEvent(socket, ‘message’).pipe(map(event => event.data));
messages.subscribe(data => console.log(data));
What are some key best practices for writing maintainable Angular code in large projects?
To ensure maintainable code in large Angular applications:
- Modular architecture: Break down the app into feature modules and lazy-load them where appropriate.
- Component reusability: Write components that are reusable and not tightly coupled to specific features.
- DRY (Don’t Repeat Yourself): Extract shared logic into services, utilities, and base components.
- Strong typing with TypeScript: Use interfaces and strong typing to make the code safer and more predictable.
- Linting and formatting: Use tools like TSLint or ESLint to enforce coding standards and maintain consistency.
How do you implement file upload functionality in an Angular application?
File uploads in Angular can be implemented using the HttpClient with FormData to send multipart file data to the backend. You can create a custom component for selecting and uploading files, handling the file validation, and progress tracking.
uploadFile(event) {
const file = event.target.files[0];
const formData = new FormData();
formData.append(‘file’, file);
this.http.post(‘api/upload’, formData).subscribe(response => {
console.log(‘File uploaded successfully’);
});
}
How do you manage authentication and authorisation in Angular applications?
Authentication in Angular is commonly handled using:
JWT (JSON Web Tokens): The user logs in, and the server returns a JWT, which is stored in localStorage or sessionStorage and sent with HTTP requests via an interceptor.
OAuth: For third-party authentication, OAuth services like Google and Facebook can be integrated.
Route guards: Use CanActivate and CanLoad route guards to restrict access to certain routes based on the user’s authentication status or roles.
canActivate(): boolean {
return this.authService.isLoggedIn();
}
What are services in Angular, and how do you create them?
Services in Angular are used to share logic, manage data, or perform specific tasks across components. Services are typically classes with specific functionality, like HTTP requests, shared data management, or utility functions. You create a service using the Angular CLI:
ng generate service my-service
How do you inject services into components?
To inject the service into a component, use Angular’s Dependency Injection (DI). You inject the service in the constructor of the component where you need it.
@Injectable({
providedIn: ‘root’, // Makes it a singleton service
})
export class MyService {
getData() {
return ‘Service Data’;
}
}
@Component({
selector: ‘app-example’,
template: <p>{{ data }}</p>
,
})
export class ExampleComponent {
data: string;
constructor(private myService: MyService) {
this.data = this.myService.getData();
}
}
What are observables in Angular?
Observables are a key part of Angular’s reactive programming model, allowing you to handle asynchronous operations such as HTTP requests, events, or streams of data.
They are provided by RxJS and can emit multiple values over time. You can subscribe to observables to react to emitted values.
How do you use observables for asynchronous operations?
For example, when retrieving data from an API, you typically work with observables from Angular’s HttpClient:
import { HttpClient } from ‘@angular/common/http’;
import { Observable } from ‘rxjs’;
export class MyService {
constructor(private http: HttpClient) {}
fetchData(): Observable<any> {
return this.http.get('https://api.example.com/data');
}
}</any>
@Component({
selector: ‘app-example’,
template: <p *ngIf="data">{{ data }}</p>
,
})
export class ExampleComponent {
data: any;
constructor(private myService: MyService) {
this.myService.fetchData().subscribe(
(response) => (this.data = response),
(error) => console.error(error)
);
}
}
How do you handle data retrieval in Angular, especially in large applications?
In large applications, handling data retrieval efficiently requires a well-structured approach:
- Service-based architecture: Create services that handle all HTTP requests and expose methods to fetch data.
- Caching: Use observables with caching mechanisms to avoid redundant API calls.
- Resolvers: Implement Angular resolvers to prefetch data before a route is activated, ensuring the component receives the necessary data when initialised.
- RxJS operators: Use operators like map, switchMap, catchError, and retry to process and manage data streams.
this.http.get(‘api/items’).pipe(
map((data) => this.transformData(data)),
retry(3),
catchError((error) => {
console.error(‘Error fetching data’, error);
return throwError(error);
})
);