All topics
Directivesbeginner

Attribute Directives

Explain what an attribute directive is and how it differs from a structural directive and a component.

An attribute directive changes the appearance or behavior of an existing DOM element without adding or removing elements from the DOM — it attaches to an element the way a class or style attribute would, hence the name. Angular's own NgClass, NgStyle, and RouterLink are all attribute directives, which is a useful set of examples to cite in an interview since they're things almost every Angular developer has used without necessarily thinking of them as "directives."

An attribute directive is like a tailor who alters an existing suit — taking in the waist, adding a monogram — without building an entirely new suit from scratch the way a component (a full outfit) would.

Key Concepts

1
The three-way distinction interviewers want to hear clearly stated: a component is a directive with a template (it creates its own view), a structural directive changes the DOM layout by adding/removing/repeating elements (it works with ng-template and a ViewContainerRef), and an attribute directive does neither — it just modifies properties, styles, classes, or behavior of the host element it's placed on, typically by injecting ElementRef and/or Renderer2, or more simply via host bindings.
ng-templateViewContainerRefElementRefRenderer2
2
A well-built attribute directive almost always prefers @HostBinding/host metadata over directly manipulating the DOM through ElementRef.nativeElement, because direct DOM manipulation bypasses Angular's abstraction layer and breaks if the app ever runs in an environment without a real DOM, like server-side rendering or a Web Worker via Renderer2's platform abstraction.
@HostBindingElementRef.nativeElementRenderer2
3
Interviewers often follow up by asking you to build a simple custom attribute directive live — commonly something like a highlight-on-hover directive — because it's small enough to write in a few minutes but touches @Directive, @HostListener, and @HostBinding (or the host metadata equivalent) all at once.
@Directive@HostListener@HostBindinghost