Cory Rylan

My name is , Google Developer Expert, Speaker, Software Developer. Building Design Systems and Web Components.

Follow @coryrylan
Angular

Angular Component Inheritance and Template Swapping

Cory Rylan

- 3 minutes

Updated

This article has been updated to the latest version Angular 17 and tested with Angular 16. The content is likely still applicable for all Angular 2 + versions.

Angular components are a fantastic way to break up our web apps into small easy to understand pieces of UI code. Sometimes in specific apps, we have drastic layout differences for the same data being displayed. An example could be differences between mobile and desktop layouts. Sometimes it could be showing our data in different formats such as a list view vs. a table view.

In these instances many times our component is a presentation component displaying this data and we have the same Inputs and Output data. In these cases, it would be beneficial to be able to swap the templates when displaying the data in different formats. In this post, we are going to use Angular Component Inheritance to derive two subcomponents to display some data. One component will be a list view and another a table view.

Angular Component Inheritance

Base Component Class

Overall I do not recommend using Component Inheritance but rather use composition to mix and match multiple components together. In this particular use case Component Inheritance is rather helpful when our templates have drastic differences in markup but display the same data.

First, we need to define our base class that contains all of the logic we want to share.

import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Employee } from './interfaces';

@Component({
  selector: 'app-employee',
  template: ''
})
export class EmployeeComponent {
  @Input() employees: Employee[] = [];
  @Output() select = new EventEmitter();

  heading = 'Employees';

  selectEmployee(employee: Employee) {
    this.select.emit(employee);
  }
}

Our base employee component has one input and one output. It takes in a list of employee objects to display and emits an event to the parent component when an employee is selected. Notice carefully that we don't have a template. This is because we are going to extend this component into a employee-list.component and employee-table.component.

Component Inheritance


import { Component } from '@angular/core';
import { EmployeeComponent } from './employee.component';

@Component({
  selector: 'app-employee-list',
  template: `
    <h1>{{heading}}</h1>
    <ul>
      <li *ngFor="let employee of employees">
        {{employee.firstName}} {{employee.lastName}} <br>
        {{employee.email}} <br>
        <button (click)="selectEmployee(employee)">Select</button>
      </li>
    </ul>
  `
})
export class EmployeeListComponent extends EmployeeComponent {
  heading = 'Employee List';
}

Above is our component that inherits our base component class. We do this by extending the class with this line of code EmployeeListComponent extends EmployeeComponent. We inherit all the input and outputs of the base class. In our list component, we override the decorator with a list template and override the heading property. Now we can reuse all of the base class logic with a different template. Below is our other component the employee-table.component.


import { Component } from '@angular/core';
import { EmployeeComponent } from './employee.component';

@Component({
  selector: 'app-employee-table',
  template: `
    <h1>{{heading}}</h1>
    <table>
      <tr>
        <td>First Name</td>
        <td>Last Name</td>
        <td>Email</td>
      </tr>
      <tr *ngFor="let employee of employees">
        <td>{{employee.firstName}}</td>
        <td>{{employee.lastName}}</td>
        <td>{{employee.email}}</td>
        <td><button (click)="selectEmployee(employee)">Select</button></td>
      </tr>
    </table>
  `
})
export class EmployeeTableComponent extends EmployeeComponent { }

We can see above that we can share our base component logic and have a drastically different template that shares the same behavior.

<app-employee-list
  [employees]="employees"
  (select)="selectEmployee($event)"
></app-employee-list>

<app-employee-table
  [employees]="employees"
  (select)="selectEmployee($event)"
></app-employee-table>

In the code above we can see both inherited child components now share the same public API.

While composition is the preferred way to use components using component inheritance can provide benefits in specific use cases. This is especially useful for UI kits and component libraries. Check out the running demo below!

View Demo Code   
Twitter Facebook LinkedIn Email
 

No spam. Short occasional updates on Web Development articles, videos, and new courses in your inbox.

Related Posts

Angular

Creating Dynamic Tables in Angular

Learn how to easily create HTML tables in Angular from dynamic data sources.

Read Article
Web Components

Reusable Component Patterns - Default Slots

Learn about how to use default slots in Web Components for a more flexible API design.

Read Article
Web Components

Reusable Component Anti-Patterns - Semantic Obfuscation

Learn about UI Component API design and one of the common anti-patterns, Semantic Obfuscation.

Read Article