Angular Portals: What Are They and How to Use Them

Introduction

If you've worked with Angular, you've likely encountered the challenge of rendering content in a different context from where it was defined. For example, you might want to display a dialog or a popover that overlays part of the page, but you don't want to include the dialog markup in the main component's template. This required complex and error-prone workarounds in the past, but now with Angular portals, it's easier than ever.

Angular portals, also known as portal components, allow you to render a part of your application in a different location in the DOM tree than where it is defined. This can be useful for building more flexible and reusable components, especially when you need to display content in a different context.

In this article, we'll explain what Angular portals are, how they work, and provide examples to demonstrate their usage.

What Are Angular Portals?

At a high level, an Angular portal can render content in a different location than where it was defined. This is achieved by creating a portal component that serves as a placeholder for the content and then using a portal outlet to attach the portal to the desired location in the DOM tree.

The portal component is a regular Angular component that defines the markup and behavior of the content you want to render. The key difference is that the portal component doesn't render the content itself; instead, it provides a slot where the content will be inserted. This slot is defined using the ng-content directive.

The portal outlet is a directive that defines the location where the portal will be rendered. The outlet can be a DOM element or another Angular component. The key benefit of using a portal outlet is that it allows you to render the content in a different location in the DOM tree than where the portal component was defined. This can be useful for cases like modals, tooltips, and other UI components that need to be rendered in a different context from where they were defined.

How to Use Angular Portals?

To use Angular portals, you'll need to follow a few steps,

Step 1. Define the Portal Component

The first step is to create the portal component that will serve as a placeholder for the content you want to render. This component should define the markup and behavior of the content, but it should not render the content itself. Instead, it should provide a slot where the content will be inserted.

Here's an example of a simple portal component that displays a message.

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

@Component({
  selector: 'app-message-portal',
  template: `
    <div class="message">
      <ng-content></ng-content>
    </div>
  `,
})
export class MessagePortalComponent {}

In this example, the MessagePortalComponent defines a slot for the content using the ng-content directive. When the portal is attached to a portal outlet, the content will be rendered inside this slot.

Step 2. Create the Portal

The next step is to create an instance of the portal component you want to render. This is typically done in the component that will host the portal.

You can create the portal instance using the ComponentPortal class from the @angular/cdk/portal package. This class takes the portal component type as an argument.

Here's an example of how to create a portal instance.

import { ComponentPortal } from '@angular/cdk/portal';
import { MessagePortalComponent } from './message-portal.component';

export class MyComponent {
  private portal = new ComponentPortal(MessagePortalComponent);
}

In this example, the MyComponent component creates a portal instance of the MessagePortalComponent.

Step 3. Attach the Portal to a Portal Outlet

Once you have a portal instance, attach it to a portal outlet in the desired location in the DOM tree. You can do this by using the PortalOutlet class from the @angular/cdk/portal package.

Here's an example of how to create a portal outlet.

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { CdkPortalOutlet } from '@angular/cdk/portal';

@Component({
  selector: 'app-my-component',
  template: `
    <div>
      <h1>Welcome to my app</h1>
      <ng-container #portalOutlet></ng-container>
    </div>
  `,
})
export class MyComponent implements AfterViewInit {
  @ViewChild(CdkPortalOutlet)
  portalOutlet: CdkPortalOutlet;

  ngAfterViewInit() {
    this.portalOutlet.attach(this.portal);
  }
}

In this example, the MyComponent component defines a portal outlet using the CdkPortalOutlet directive. This directive creates a placeholder where the portal will be rendered.

In the ngAfterViewInit lifecycle hook, the portal is attached to the portal outlet using the attach method. This method takes the portal instance created in step 2 as an argument.

Step 4. Use the Portal

Finally, you can use the portal by adding content to it. This is done by including the content you want to render inside the portal component tags.

Here's an example of how to use the portal to display a message.

<app-my-component>
  <app-message-portal>
    Hello, world!
  </app-message-portal>
</app-my-component>

In this example, the app-my-component component hosts the portal, and the content to be rendered is included inside the app-message-portal tags.

Benefits of Using Angular Portals

Using Angular portals offers several benefits,

  1. Separation of concerns- By defining a portal component that provides a slot for the content, you can separate the markup and behavior of the content from the location where it will be rendered.
  2. Reusability- Portals can be reused in different contexts, allowing you to build more flexible and reusable components.
  3. Improved performance- Portals use the Angular Change Detection system to efficiently update the content when it changes, improving performance compared to other approaches.
  4. Better accessibility- By using a portal component that defines the semantics and accessibility of the content, you can ensure that the rendered content is accessible and follows best practices.

Examples of Using Angular Portals

Here are some examples of how you can use Angular portals in your applications:

  1. Modals- Use a portal to render a modal dialog that overlays part of the page.
  2. Tooltips- Use a portal to render a tooltip that appears when the user hovers over an element.
  3. Popovers- Use a portal to render a popover that displays additional information when the user clicks on an element.
  4. Dynamic forms- Use a portal to render form fields based on user input or other conditions.

Conclusion

In this article, we've explained what Angular portals are, how they work, and provided examples to demonstrate their usage. Using portals, you can build more flexible and reusable components and improve the performance and accessibility of your applications. With these benefits, it's clear that Angular portals are a powerful tool every Angular developer should add to their toolkit.