Generic component where projected content is instantiated in outer zone

78 Views Asked by At

I have a webcomponent that for perf reasons needs to run outside angular.

I came up with the basic idea :

@Component({
  selector: 'run-outer-zone',
  template: ''
}) 
class OuterZoneComponent {
   constructor(private vcr: ViewContainerRef, private ngZone: NgZone) {
      this.ngZone.runOutsideAngular(() => {
          const compRef = vcr.createComponent(MyComponentWhichNeedsToRunOutsideAngular);
          compRef.data = // set the inputs
      })
   }
}

It works fine but that's not very generic and it's cumbersome if have multiple web components to handle.

Is it possible to build a custom generic component where the projected content is run in the outer zone ?

1

There are 1 best solutions below

0
Matthieu Riegler On BEST ANSWER

I ended up writing my own directive to run specific components outside the NgZone.

It's hugely inspired by how the NgIf works.

@Directive({
  selector: '[runOutside]',
  standalone: true,
})
export class RunOutsideDirective<T> {
  private isOutside: boolean;

  constructor(
    private _viewContainer: ViewContainerRef,
    private ngZone: NgZone,
    private templateRef: TemplateRef<T>
  ) {}

  ngOnInit() {
    this.updateView(true);
  }

  @Input()
  set runOutside(doRunOutside) {
    this.updateView(doRunOutside);
  }

  private updateView(doRunOutside: boolean) {
    if (doRunOutside === this.isOutside) {
      return;
    }

    this._viewContainer.clear();
    if (doRunOutside) {
      this.ngZone.runOutsideAngular(() => {
        this._viewContainer.createEmbeddedView(this.templateRef);
      });
    } else {
      this._viewContainer.createEmbeddedView(this.templateRef);
    }
  }
}

usage :

<my-cmp *runOutside></my-cmp>