Pass Angular Component via @Input() | HOC | Dynamic Wrapper

The intro

I was working with React Projects for a long time. I have evolved a mindset that allows you to abuse HOC to make code more reusable and somewhat clean. But when I got into Angular, it felt weird at first that there is no such concept.

The spark

At some point, I got in touch with Modals and there it was the gong that awoke the ninja in me. First, I dove again into angular.io docs and indeed found a way to pass components through @Input() and render them. But that was unsatisfying because of the directive. That could be because decorators are something new after React. Or because it splits such a simple concept as HOC into too many files.

The sandbox

Here I have created a small code sandbox after my researches. You can see how a component can be rendered from a variable. I got deeper into Angular docs. Found a matching pattern between template variables and @directive. The directive was necessary only to extract reference to the element. As a result HOC got more simple and it is more close to the concept I got used to:

Stackblitz code sandbox

Ionic Modal Angular

async openModal() {
  const modal = await this.modalController.create({
    component: ModalWrapperComponent,
    componentProps: {
      bodyComponent: ModalComponent,
      bodyComponentInputs: { key: 'value' }
    },
  });

  modal.present();
}

Material Dialog Angular

openDialog(): void {
  const dialogRef = this.dialog
    .open(ModalWrapperComponent, {
      data: {
        bodyComponent: ModalComponent,
        bodyComponentInputs: { key: 'value' }
      },
    });
}

The takeaway

I hope this article helps anyone that wants to understand more deeply how Angular works and how to be a ninja with HOC in Angular. I went geek-serk after a few weeks of Angular without this pattern. And this article emerged because there were no good answers out there in the wild about passing components to components.

For those who want a HOC with the less dynamic inner component. Here is a version with *ngTemplateOutlet. The difference is that this is more simple and cannot pass any inputs into the wrapped component. Stackblitz code sandbox (template outlet)