Components vs Directives


Components vs Directives Interview with follow-up questions

1. What is the main difference between components and directives in Angular?

The defining difference is the template: a component has its own view, a directive does not. A component (@Component) renders a region of UI and is the main building block; a directive (@Directive) attaches behavior or appearance to an existing host element.

Under the hood a component is simply a directive with a template — they share the same lifecycle hooks and DI, which is why this question is really about that one structural distinction. Directives come in two flavors: attribute (e.g. ngClass, custom [highlight]) and structural (the legacy *ngIf/*ngFor).

A current aside that impresses: because they share a base, modern Angular lets a component compose directive behavior via hostDirectives, applying a directive's logic without inheritance — useful for reusing cross-cutting behavior (accessibility, analytics) across components.

↑ Back to top

Follow-up 1

Can you give an example of when you would use a component over a directive?

Components are typically used when you want to create a reusable UI element that encapsulates its own behavior and template. For example, if you want to create a custom button with specific styling and functionality, you would create a component. Directives, on the other hand, are used when you want to manipulate the behavior or appearance of existing elements in the DOM without creating a separate UI element.

Follow-up 2

What are some of the common directives used in Angular?

Some of the common directives used in Angular are:

  • ngIf: Used to conditionally show or hide elements based on a condition.
  • ngFor: Used to iterate over a collection and render elements for each item.
  • ngClass: Used to add or remove CSS classes based on a condition.
  • ngStyle: Used to dynamically apply inline styles to elements.
  • ngModel: Used for two-way data binding between a form control and a component.
  • ngSubmit: Used to handle form submission events.
  • ngSwitch: Used to conditionally render elements based on a specific value.

Follow-up 3

How do you define a custom directive in Angular?

To define a custom directive in Angular, you can use the @Directive decorator. Here's an example:

import { Directive, ElementRef } from '@angular/core';

@Directive({
  selector: '[appCustomDirective]'
})
export class CustomDirective {
  constructor(private elementRef: ElementRef) {
    this.elementRef.nativeElement.style.backgroundColor = 'red';
  }
}

In this example, the custom directive is applied to elements with the attribute 'appCustomDirective'. The directive's constructor injects the ElementRef, which gives access to the DOM element that the directive is applied to. In this case, the directive sets the background color of the element to red.

2. How can you identify whether a particular element in Angular is a component or a directive?

The quickest tell is how it's used in the template: a component is applied as its own element (`), because its selector is an element selector; a **directive** is applied as an **attribute** on an existing element (

`), because its selector is an attribute selector.

In the source code, the distinction is the decorator and a template: @Component (has template/templateUrl) versus @Directive (no view of its own).

A caveat worth raising so you don't sound absolutist: selectors are flexible — a component can use an attribute selector ([appWidget]) and a directive can match elements — so "custom tag = component, attribute = directive" is a strong heuristic, not a hard rule. The reliable answer is: whatever has a template is a component.

↑ Back to top

Follow-up 1

What are the key parts of a component?

The key parts of a component in Angular are:

  1. Template: The HTML markup that defines the component's view.
  2. Class: The TypeScript class that contains the component's logic and data.
  3. Metadata: The decorator that provides Angular with information about the component, such as its selector, template, and styles.

Follow-up 2

What are the key parts of a directive?

The key parts of a directive in Angular are:

  1. Selector: The attribute or element that triggers the directive.
  2. Host: The element that the directive is attached to.
  3. Template: The HTML markup that defines the directive's behavior.
  4. Class: The TypeScript class that contains the directive's logic and data.
  5. Metadata: The decorator that provides Angular with information about the directive, such as its selector and template.

Follow-up 3

Can a component be used as a directive?

Yes, a component can be used as a directive in Angular. Components are a type of directive that have their own view, while other types of directives typically modify the behavior or appearance of existing elements. By using a component as a directive, you can reuse the component's logic and data without rendering its view.

3. Can you explain the lifecycle of a component and a directive in Angular?

Components and directives share the same lifecycle, implemented through lifecycle hook interfaces Angular calls in order:

  • ngOnChanges — when a data-bound input changes (receives a SimpleChanges map).
  • ngOnInit — once, after the first inputs are set; do initialization/data loading here.
  • ngDoCheck — on every change-detection run, for custom change detection.
  • ngAfterContentInit / ngAfterContentChecked — projected content (ng-content) initialized/checked. (component-only)
  • ngAfterViewInit / ngAfterViewChecked — the component's own view and child views initialized/checked. (component-only)
  • ngOnDestroy — just before destruction; clean up subscriptions/timers here.

The difference: a directive has no view or projected content, so it only gets the hooks up to ngDoCheck plus ngOnDestroy — the AfterContent*/AfterView* hooks are component-only.

A strong modern addition: with signals, much state that used to need ngOnChanges/ngDoCheck is now handled reactively with computed() and effect(), and the new afterRenderEffect/afterNextRender APIs cover post-render DOM work — so you reach for the classic hooks less often.

↑ Back to top

Follow-up 1

What are the different lifecycle hooks available for a component?

In Angular, there are several lifecycle hooks available for a component. These hooks allow you to tap into different stages of the component's lifecycle and perform certain actions. The different lifecycle hooks available for a component are as follows:

  1. ngOnChanges: This hook is called whenever there is a change in the component's input properties. It receives a SimpleChanges object that contains the previous and current values of the input properties.

  2. ngOnInit: This hook is called after the component's constructor and ngOnChanges hook have been called for the first time. It is used for initialization tasks such as retrieving data from a server.

  3. ngDoCheck: This hook is called during every change detection cycle. It is used to detect and act upon changes that Angular cannot detect automatically.

  4. ngAfterContentInit: This hook is called after Angular projects external content into the component's view.

  5. ngAfterContentChecked: This hook is called after Angular checks the content projected into the component's view.

  6. ngAfterViewInit: This hook is called after Angular initializes the component's view and child views.

  7. ngAfterViewChecked: This hook is called after Angular checks the component's view and child views.

  8. ngOnDestroy: This hook is called just before the component is destroyed. It is used for cleanup tasks such as unsubscribing from observables and releasing resources.

Follow-up 2

What are the different lifecycle hooks available for a directive?

In Angular, there are several lifecycle hooks available for a directive. These hooks allow you to tap into different stages of the directive's lifecycle and perform certain actions. The different lifecycle hooks available for a directive are as follows:

  1. ngOnChanges: This hook is called whenever there is a change in the directive's input properties. It receives a SimpleChanges object that contains the previous and current values of the input properties.

  2. ngOnInit: This hook is called after the directive's constructor and ngOnChanges hook have been called for the first time. It is used for initialization tasks such as retrieving data from a server.

  3. ngDoCheck: This hook is called during every change detection cycle. It is used to detect and act upon changes that Angular cannot detect automatically.

  4. ngOnDestroy: This hook is called just before the directive is destroyed. It is used for cleanup tasks such as unsubscribing from observables and releasing resources.

Follow-up 3

Can you give an example of how you would use a lifecycle hook in a component or directive?

Sure! Let's take the example of the ngOnChanges hook, which is called whenever there is a change in the component or directive's input properties. Suppose we have a component that takes an input property called 'name'. We can use the ngOnChanges hook to perform some action whenever the 'name' input property changes. Here's an example:

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `<p>Hello, {{ name }}!</p>`
})
export class ExampleComponent implements OnChanges {
  @Input() name: string;

  ngOnChanges(changes: SimpleChanges) {
    if (changes.name) {
      console.log('The name input property has changed.');
      console.log('Previous value:', changes.name.previousValue);
      console.log('Current value:', changes.name.currentValue);
    }
  }
}

In this example, whenever the 'name' input property changes, the ngOnChanges hook is called and we log the previous and current values of the 'name' input property.

This is just one example, and there are many other ways to use lifecycle hooks in components and directives depending on your specific use case.

4. What is the purpose of the @Component and @Directive decorators in Angular?

Both are class decorators that attach metadata, telling Angular how to treat the class and supplying its selector and configuration.

  • @Component defines a UI building block with a template. Its metadata includes selector, template/templateUrl, styles, imports (for standalone), changeDetection, and providers. Angular uses it to instantiate the class and render its view.
  • @Directive defines behavior attached to an existing host element, without its own template. Its metadata includes selector, host bindings, and providers. Use it for attribute/structural behavior (styling, event handling, DOM manipulation).

The relationship to emphasize: @Component is essentially @Directive plus a view — components are a specialization of directives, sharing DI and lifecycle. A current note: under both decorators, classes are standalone by default in modern Angular, declaring their own dependencies rather than being registered in an NgModule.

↑ Back to top

Follow-up 1

What information do you provide to the @Component decorator?

The @Component decorator accepts an object as an argument, which contains various properties to configure the component. Some of the commonly used properties are:

  • selector: Specifies the CSS selector that identifies the component in a template.
  • template/templateUrl: Specifies the HTML template for the component.
  • styles/styleUrls: Specifies the CSS styles for the component.
  • providers: Specifies the services that the component requires.

Here is an example of how you would use the @Component decorator:

import { Component } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<h1>Hello, World!</h1>',
  styles: ['h1 { color: red; }']
})
export class ExampleComponent {
  // Component logic goes here
}

Follow-up 2

What information do you provide to the @Directive decorator?

The @Directive decorator accepts an object as an argument, which contains various properties to configure the directive. Some of the commonly used properties are:

  • selector: Specifies the CSS selector that identifies the elements to which the directive should be applied.
  • inputs/outputs: Specifies the input and output properties of the directive.
  • host: Specifies the event listeners and host properties of the directive.

Here is an example of how you would use the @Directive decorator:

import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[appExample]'
})
export class ExampleDirective {
  constructor(private elementRef: ElementRef) {}

  @HostListener('click')
  onClick() {
    this.elementRef.nativeElement.style.backgroundColor = 'red';
  }
}

Follow-up 3

Can you give an example of how you would use the @Component and @Directive decorators?

Sure! Here is an example of how you would use both the @Component and @Directive decorators:

import { Component, Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[appExample]'
})
export class ExampleDirective {
  constructor(private elementRef: ElementRef) {}

  @HostListener('click')
  onClick() {
    this.elementRef.nativeElement.style.backgroundColor = 'red';
  }
}

@Component({
  selector: 'app-example',
  template: '<h1>Hello, World!</h1>',
  styles: ['h1 { color: blue; }']
})
export class ExampleComponent {
  // Component logic goes here
}

5. How do you handle events in components and directives?

You handle events with event binding — the (event)="handler($event)" syntax — which works the same on a component's template elements and on a directive's host element.

In a component template:

Save

In a directive, you bind to events on the host element with @HostListener (or the host metadata):

@Directive({ selector: '[appConfirm]' })
export class ConfirmDirective {
  @HostListener('click', ['$event'])
  onClick(e: MouseEvent) { /* … */ }
}

Points interviewers like: $event carries the native event (or a custom value emitted via @Output()/output()); Angular supports key/event modifiers like (keyup.enter); and to send events up from a child component you emit through an output()/EventEmitter, which the parent binds with (myEvent). With zoneless change detection, event handlers still trigger updates because they run through Angular's event-handling path.

↑ Back to top

Follow-up 1

What is event binding in Angular?

Event binding in Angular is a way to handle events raised by HTML elements or Angular directives. It allows you to listen to events such as button clicks, mouse movements, and keyboard inputs, and execute a function or perform some action in response to those events. Event binding is denoted by the (event) syntax in Angular templates.

Follow-up 2

How do you bind to user input events like clicks and key presses?

To bind to user input events like clicks and key presses, you can use event binding in Angular. For example, to bind to a button click event, you can use the (click) event binding syntax. Similarly, to bind to a key press event, you can use the (keyup) or (keydown) event binding syntax. Inside the event binding expression, you can call a method or execute any JavaScript code to handle the event.

Follow-up 3

Can you give an example of how you would use event binding in a component or directive?

Sure! Here's an example of how you can use event binding in an Angular component:

Click me

In this example, the (click) event binding is used to bind the handleButtonClick() method to the button's click event. When the button is clicked, the handleButtonClick() method will be executed. You can define the handleButtonClick() method in the component's TypeScript code to perform any desired action.

Live mock interview

Mock interview: Components vs Directives

Intermediate ~5 min Your own free AI key

Your voice and your AI key never touch our servers; the key stays in this browser and is sent only to Google. Only your round scores are saved to track progress.