DEV Community

Ferdie Sletering
Ferdie Sletering

Posted on

Angular Material Tabs with components inside the tabs

My use case was to render components inside the Angular Material Tabs component. Despite searching online, I couldn't find any relevant resources, so I had to figure it out myself.

Below is the structure we want to use to define the components that should be displayed inside the tabs:

 tabs = <Tab[]>[
    {
      label: 'Tab Component',
      component: TabComponent,
      data: {
        title: 'Tab 1 Import information',
        content: `Donec lacinia condimentum efficitur. Phasellus tempor est in luctus
        facilisis.`,
      },
    },
    {
      label: 'Random component',
      component: RandomComponent,
      data: {
        text: 'Text passed on from the random component',
      },
    },
  ];
Enter fullscreen mode Exit fullscreen mode

Component

Here's the complete code snippet for the component that renders the components inside the tab container.

type Tab = {
  label: string;
  component: Type<any>;
  data: Record<string, any>;
};

@Component({
  selector: 'app-tabcontainer',
  standalone: true,
  imports: [MatTabsModule],
  templateUrl: './tabcontainer.component.html',
  styleUrl: './tabcontainer.component.css',
})
export class TabcontainerComponent {
  viewContainerRef = inject(ViewContainerRef);
  tabs = <Tab[]>[
    {
      label: 'Tab Component',
      component: TabComponent,
      data: {
        title: 'Tab 1 Import information',
        content: `Donec lacinia condimentum efficitur. Phasellus tempor est in luctus
        facilisis.`,
      },
    },
    {
      label: 'Random component',
      component: RandomComponent,
      data: {
        text: 'Text passed on from the random component',
      },
    },
  ];

  ngOnInit() {
    this.loadComponent(this.tabs[0]);
  }

  loadComponent(tab: Tab) {
    this.viewContainerRef.clear();
    const ref = this.viewContainerRef.createComponent<any>(tab.component);

    // Pass on the props
    for (const prop in tab.data) {
      if (Object.prototype.hasOwnProperty.call(ref.instance, prop)) {
        ref.instance[prop] = tab.data[prop];
      }
    }
  }

  onTabSelected(index: number) {
    this.loadComponent(this.tabs[index]);
  }
}
Enter fullscreen mode Exit fullscreen mode

Caching the tabs

I conducted performance testing to see if caching the component references and loading them from the cache upon request would improve render time. However, there was no improvement in render time.

Angular signals

The code doesn't work with input() signals yet.

Demo

Try the stackblitz

Top comments (0)