Angular basics
What is Angular?
Angular is a complete frontend framework from Google, written in TypeScript. Unlike a library, it already includes routing, HTTP, forms, dependency injection and testing, so a large team does not have to choose and glue those pieces together.
What is the difference between AngularJS and Angular?
AngularJS is the old 1.x version written in JavaScript, using scopes, controllers and dirty checking. Angular from version 2 onwards is a complete rewrite in TypeScript with components, a proper dependency injection system and much better performance. They are not compatible.
What is a component?
A component is one piece of the screen: a TypeScript class for the logic, an HTML template for the view, and CSS for the style, tied together by the @Component decorator. Every Angular app is a tree of components starting at the root.
@Component({
selector: "app-user-card",
standalone: true,
template: `<h3>{{ name }}</h3>`,
})
export class UserCardComponent {
@Input() name = "";
}
What is a module (NgModule)?
An NgModule groups components, directives, pipes and providers that belong together and declares what they can use and what they expose. Modern Angular prefers standalone components, where each component lists its own imports, so NgModules are becoming optional.
What is a standalone component?
A component that does not belong to any NgModule. It sets standalone: true and imports whatever it needs directly. It removes a whole layer of boilerplate and makes lazy loading a single component possible.
What is a directive and what types are there?
A directive adds behaviour to an existing element. Structural directives change the DOM layout and start with a star, like *ngIf and *ngFor. Attribute directives change appearance or behaviour, like ngClass and ngStyle. A component is technically a directive with a template.
What is data binding in Angular?
There are four kinds. Interpolation {{ value }} puts data in the template. Property binding [prop] passes data down. Event binding (click) sends events up. Two-way binding [(ngModel)] does both at once and is just the other two combined.
<input [value]="name" (input)="name = $event.target.value" />
<!-- same as -->
<input [(ngModel)]="name" />
What is the difference between a constructor and ngOnInit?
The constructor runs when the class is created and should only be used for dependency injection. ngOnInit runs after Angular has set the input properties, so that is where you read inputs and start your setup work.
What are the lifecycle hooks in order?
ngOnChanges when an input changes, ngOnInit once after the first inputs, ngDoCheck on every check, ngAfterContentInit and ngAfterContentChecked for projected content, ngAfterViewInit and ngAfterViewChecked for the view and child views, and ngOnDestroy just before the component is removed.
What do you do in ngOnDestroy?
Clean up: unsubscribe from manual subscriptions, clear intervals, remove event listeners and disconnect observers. Skipping this is the most common cause of memory leaks in Angular apps.
What is content projection and ng-content?
It lets a parent pass markup into a child component template, which is Angular version of React children. Use a select attribute to project different pieces into different slots.
<!-- card.component.html -->
<div class="card">
<header><ng-content select="[card-title]"></ng-content></header>
<ng-content></ng-content>
</div>
What is the difference between ng-template, ng-container and ng-content?
ng-template holds markup that is not rendered until something asks for it - structural directives use it. ng-container is an invisible grouping element that lets you apply a directive without adding a real DOM node. ng-content is the slot where a parent projected content appears.
What is the AsyncPipe and why is it recommended?
It subscribes to an Observable in the template, shows the latest value, and unsubscribes automatically when the component is destroyed. That removes a whole class of memory leak bugs, so it is the preferred way to consume observables in a view.
<div *ngIf="user$ | async as user">{{ user.name }}</div>
Dependency injection and services
What is dependency injection?
Instead of a class creating the things it needs, Angular creates them and passes them in. That makes classes easier to test, because you can pass a fake service, and easier to reuse, because the class does not care where the dependency came from.
@Injectable({ providedIn: "root" })
export class UserService {
constructor(private http: HttpClient) {}
}
// in a component
constructor(private users: UserService) {}
// or the modern form
private users = inject(UserService);
What does providedIn: "root" mean?
The service is registered once for the whole application and one shared instance is created the first time something injects it. It is also tree-shakable - if nothing uses the service, it is dropped from the bundle.
What is the difference between providing a service in root and in a component?
In root there is one instance for the whole app, so state is shared. Provided in a component, a new instance is created for each instance of that component and destroyed with it, which is useful for per-form or per-widget state.
What is an injection token?
A unique key used to inject something that is not a class, such as a configuration object or a string. You create it with new InjectionToken and provide a value for it.
export const API_URL = new InjectionToken<string>("API_URL");
// provide: { provide: API_URL, useValue: "https://api.example.com" }
What is the difference between useClass, useValue, useFactory and useExisting?
useClass instantiates a class, useValue supplies a ready value, useFactory calls a function that builds the value and can depend on other services, and useExisting makes a new token point at an existing provider.
What is an HTTP interceptor?
A piece of code that sees every outgoing request and incoming response. It is where you add an auth token, log timings, show a global loader or retry on failure, without touching each service.
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = inject(AuthService).token;
return next(req.clone({ setHeaders: { Authorization: "Bearer " + token } }));
};
Why does HttpClient return an Observable and not a Promise?
Because an Observable can be cancelled, retried and combined with operators, and it can emit more than once. Cancelling matters a lot for search-as-you-type, where switchMap drops the previous request automatically.
Do you have to unsubscribe from HttpClient?
HttpClient completes after one value, so it cleans itself up. You should still cancel it when the component is destroyed if the request is long running - the AsyncPipe or takeUntilDestroyed does that for you.
Routing
How does Angular routing work?
You define an array of routes mapping a path to a component. The router watches the URL and renders the matching component inside <router-outlet>. Order matters, because the first match wins.
export const routes: Routes = [
{ path: "", component: HomeComponent },
{ path: "users/:id", component: UserComponent },
{ path: "**", component: NotFoundComponent },
];
What is lazy loading in Angular?
Loading a feature bundle only when the user navigates to it, using loadComponent or loadChildren. It keeps the first download small, which matters most on slow connections.
{ path: "admin", loadComponent: () => import("./admin/admin.component").then((m) => m.AdminComponent) }
What is a route guard?
A function that runs before navigation and returns true, false or a redirect. CanActivate protects a page, CanDeactivate warns about unsaved changes, and a resolver loads data before the route activates.
export const authGuard: CanActivateFn = () => {
const auth = inject(AuthService);
return auth.isLoggedIn() || inject(Router).createUrlTree(["/login"]);
};
What is the difference between ActivatedRoute snapshot and observables?
The snapshot gives the value once. The params and queryParams observables keep emitting, which matters when the user navigates from /users/1 to /users/2 and the component is reused rather than recreated.
What is the difference between a route parameter and a query parameter?
A route parameter is part of the path and usually identifies a resource, like /users/42. A query parameter comes after the question mark and usually carries optional filters, like ?page=2&sort=name.
What is a resolver?
A function that fetches data before the route is activated, so the component renders with data already available instead of showing an empty state. The trade-off is that navigation feels slower.
Signals and modern Angular
What is a signal?
A signal is a value that knows who reads it. When it changes, only the places that actually use it are updated - no tree walking. It makes change detection precise and is the basis for zoneless Angular.
count = signal(0);
double = computed(() => this.count() * 2);
increment() { this.count.update((c) => c + 1); }
What is the difference between signal, computed and effect?
signal holds a writable value. computed derives a value from other signals and caches it until they change. effect runs side effects when the signals it reads change - it should not be used to set other signals.
What is the difference between a signal and an Observable?
A signal always has a current value you can read synchronously and is meant for state. An Observable is a stream over time that may emit zero or many values and is meant for events and async work. They coexist: toSignal and toObservable convert between them.
What is the new control flow syntax?
Angular now has built-in template blocks - @if, @for, @switch and @defer - that replace *ngIf and *ngFor. They are faster, do not need an import, and @for requires a track expression, which prevents the missing-trackBy performance bug.
@if (user(); as u) {
<p>{{ u.name }}</p>
} @else {
<p>Loading...</p>
}
@for (item of items(); track item.id) {
<li>{{ item.name }}</li>
}
What does @defer do?
It delays loading a block of the template and its JavaScript until a condition is met - the block enters the viewport, the user interacts, or the browser is idle. It is lazy loading at the template level.
What is takeUntilDestroyed?
An RxJS operator from Angular that completes a subscription automatically when the component or service is destroyed, replacing the old destroy$ Subject pattern.
this.service.data$
.pipe(takeUntilDestroyed())
.subscribe((data) => this.rows = data);
What is Angular Universal / SSR?
Rendering the app on the server so the browser gets real HTML on first load. It improves perceived speed and SEO. Watch out for code that touches window or document, because those do not exist on the server.
What is ViewChild and ContentChild?
ViewChild gets a reference to an element or component in this component own template, available from ngAfterViewInit. ContentChild gets one from the content projected into it, available from ngAfterContentInit.
How do you share data between unrelated components?
Through a service that holds the state, exposed as a signal or a BehaviorSubject, and injected into both components. For a large app with complex flows, a state library such as NgRx does the same thing with more structure.
How do you test an Angular component?
With TestBed to configure a testing module, then create the component fixture, call detectChanges and assert on the rendered DOM. Replace real services with spies or stubs so tests are fast and deterministic.