Is it possible to display single instance of an angular component in multiple places?

This answer is based on the stackblitz example provided in this answer to a similar question I asked.

Step #1: Create a directive that you will use wherever you want to have your reusable component.

@Directive({
  selector: '[reusable-outlet]',
})
export class ReusableDirective implements OnInit {

  constructor(
    private viewContainerRef: ViewContainerRef,
    private reusableService: ReusableService
  ) { }

  public ngOnInit(): void {
    this.reusableService.attach(this.viewContainerRef);
  }

}

Step #2 Create the service that will be in charge of:

  • dynamically creating the component that will be reused
  • attaching and detaching that component to the view container of the directive created in step ~1.

Note: Knowing when to detach the component is based on router events, but it should be possible to base it on messages instead, if you need to change where your component is without having navigation changes.

@Injectable()
export class ReusableService {

  private componentRef: ComponentRef<ReusableComponent>;

  private currentViewContainerRef: ViewContainerRef;

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private injector: Injector,
    private router: Router
  ) {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(ReusableComponent);
    this.componentRef = componentFactory.create(injector);

    this.router.events.subscribe(event => {
      if (event instanceof NavigationStart && this.currentViewContainerRef) {
        this.detach(this.currentViewContainerRef);
      }
    });
  }

  public attach(viewContainerRef: ViewContainerRef) {
    this.currentViewContainerRef = viewContainerRef;
    viewContainerRef.insert(this.componentRef.hostView);
  }

  public detach(viewContainerRef: ViewContainerRef) {
    viewContainerRef.detach(viewContainerRef.indexOf(this.componentRef.hostView));
  }

}

Tags:

Angular