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 big team does not have to pick and join those pieces itself.
What is the difference between AngularJS and Angular?
AngularJS is the old 1.x version, written in JavaScript, with scopes, controllers and dirty checking. Angular from version 2 is a full rewrite in TypeScript, with components, a real dependency injection system and much better speed. The two are not compatible.
What is a component?
A component is one piece of the screen. It has a TypeScript class for the logic, an HTML template for the view, and CSS for the style. The @Component decorator joins them. Every Angular app is a tree of components that starts 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. It says what they can use and what they give to others. Modern Angular prefers standalone components, where each component lists its own imports, so NgModules are becoming optional.
What is a standalone component?
A standalone component belongs to no NgModule. It sets standalone: true and imports what it needs directly. That removes a whole layer of extra code and makes it possible to lazy load a single component.
What is a directive and what types are there?
A directive adds behaviour to an element that already exists. Structural directives change the DOM layout and start with a star, like *ngIf and *ngFor. Attribute directives change look or behaviour, like ngClass and ngStyle. A component is really a directive with a template.
What is data binding in Angular?
There are four kinds. Interpolation {{ value }} puts data into the template. Property binding [prop] sends data down. Event binding (click) sends events up. Two-way binding [(ngModel)] does both, and it is just the other two joined.
<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. Use it only for dependency injection. ngOnInit runs after Angular has set the input properties. So read inputs and start your setup work there.
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. 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?
Content projection lets a parent pass markup into the template of a child component. It is the Angular version of React children. Use a select attribute to send 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 group. It lets you apply a directive without adding a real DOM node. ng-content is the slot where content from the parent appears.
What is the AsyncPipe and why is it recommended?
The AsyncPipe subscribes to an Observable in the template, shows the latest value, and unsubscribes on its own when the component is destroyed. That removes a whole group of memory leak bugs, so it is the preferred way to use observables in a view.
<div *ngIf="user$ | async as user">{{ user.name }}</div>
Dependency injection and services
What is dependency injection?
With dependency injection, a class does not create the things it needs. Angular creates them and passes them in. That makes classes easier to test, because you can pass a fake service. It also makes them 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 app. 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 the state is shared. Provided in a component, a new instance is created for each instance of that component and destroyed with it. That is useful for state that belongs to one form or one widget.
What is an injection token?
An injection token is a unique key used to inject something that is not a class, such as a settings object or a string. You create it with new InjectionToken and then 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 creates a class. useValue gives a ready value. useFactory calls a function that builds the value and can use other services. useExisting makes a new token point at a provider that already exists.
What is an HTTP interceptor?
An interceptor is code that sees every request going out and every response coming in. It is the right place to 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 joined with operators, and it can emit more than once. Cancelling matters a lot for search as you type, where switchMap drops the earlier request on its own.
Do you have to unsubscribe from HttpClient?
HttpClient completes after one value, so it cleans itself up. Still cancel it when the component is destroyed if the request is slow. The AsyncPipe or takeUntilDestroyed does that for you.
Routing
How does Angular routing work?
You write an array of routes that map 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?
Lazy loading means the bundle for a feature is downloaded only when the user goes there, 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 guard is a function that runs before navigation and returns true, false or a redirect. CanActivate protects a page. CanDeactivate warns about unsaved changes. A resolver loads data before the route opens.
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. That matters when the user moves from /users/1 to /users/2 and Angular reuses the component instead of creating a new one.
What is the difference between a route parameter and a query parameter?
A route parameter is part of the path and usually names 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 resolver is a function that loads data before the route opens, so the component renders with data instead of 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 really use it are updated. There is no walking of the whole tree. It makes change detection exact and is the base of 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 value you can write to. computed builds a value from other signals and caches it until they change. effect runs side effects when the signals it reads change. Do not use an effect to set other signals.
What is the difference between a signal and an Observable?
A signal always has a current value that you can read at once, and it is meant for state. An Observable is a stream over time that may emit zero or many values, and it is meant for events and async work. Both can live together: toSignal and toObservable convert between them.
What is the new control flow syntax?
Angular now has template blocks built in: @if, @for, @switch and @defer. They replace *ngIf and *ngFor. They are faster, need no import, and @for requires a track expression, which prevents the missing-trackBy speed 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?
@defer delays loading a block of the template and its JavaScript until a condition is met. The block can wait until it enters the screen, until the user interacts, or until the browser is idle. It is lazy loading at template level.
What is takeUntilDestroyed?
It is an RxJS operator from Angular that ends a subscription on its own when the component or service is destroyed. It replaces the old destroy$ Subject pattern.
this.service.data$
.pipe(takeUntilDestroyed())
.subscribe((data) => this.rows = data);
What is Angular Universal / SSR?
It means rendering the app on the server, so the browser gets real HTML on the first load. The page feels faster and SEO improves. Watch out for code that uses window or document, because they do not exist on the server.
What is ViewChild and ContentChild?
ViewChild gets a reference to an element or component in this component's own template. It is ready from ngAfterViewInit. ContentChild gets one from the content that a parent projected in. It is ready from ngAfterContentInit.
How do you share data between unrelated components?
Use a service that holds the state, exposed as a signal or a BehaviorSubject, and inject it into both components. For a large app with complex flows, a state library such as NgRx does the same job with more structure.
How do you test an Angular component?
Use TestBed to set up a testing module. Create the component fixture, call detectChanges, then check the rendered DOM. Replace real services with spies or stubs so the tests stay fast and give the same result every time.