Templates
Directives & custom structural directives
Structural vs attribute directives, host bindings, and writing your own with TemplateRef.
Structural directives add or remove DOM subtrees; the modern block syntax @if/@for/@switch supersedes *ngIf/*ngFor. Under the hood a structural directive receives a TemplateRef and a ViewContainerRef and stamps views in and out.
A structural directive is a stagehand rolling scenery on and off; an attribute directive is the lighting rig restyling what is already on stage.
Key concepts
1
Attribute directives change an existing element — built-ins ngClass/ngStyle, or your own using @HostBinding (bind a host property) and @HostListener (react to host events).
Attribute directivesngClassngStyle@HostBinding@HostListener
2
@for mandates a track expression: without stable identity Angular destroys and recreates DOM on every change, losing focus and animation state and tanking performance on large lists.
`track`@fortrack
3
Best practice: encapsulate cross-cutting DOM behaviour (permissions, tooltips, lazy images) as attribute directives instead of copy-pasting logic into components. Interview angle: be able to write a *appUnless structural directive from scratch.
Best practice:Interview angle:*appUnless
typescript
@Directive({ selector: '[appUnless]', standalone: true })
export class UnlessDirective {
private hasView = false;
constructor(private tpl: TemplateRef<unknown>, private vcr: ViewContainerRef) {}
@Input() set appUnless(condition: boolean) {
if (!condition && !this.hasView) { this.vcr.createEmbeddedView(this.tpl); this.hasView = true; }
else if (condition && this.hasView) { this.vcr.clear(); this.hasView = false; }
}
}