title: Is it good idea to use ComponentFactoryResolver in Angular7 application?
body: <p>I want to create an angular 7 web application that dynamically loads different components, as demonstrated in this official documentation:
  <a href="https://angular.io/guide/dynamic-component-loader" rel="nofollow noreferrer">https://angular.io/guide/dynamic-component-loader</a></p>
  <p>But I am not sure if it's a good idea to use <code>ComponentFactoryResolver</code>.
  I never used it and I don't know if it is stable and I don't know about the performance either.</p>
  <p>I would like some opinions about it and if anyone knows any alternatives.
  I don't want to use <code>native innerHTML</code></p>
  <p>I am trying to create a custom and generic wizard with dynamic steps.
  This wizard has</p>
  <ul>
  <li>header component</li>
  <li>wizard steps</li>
  <li>a &quot;container&quot;. Right now I am using ng-template to display the content of each step(a separate component, in some cases a complicated component)</li>
  <li>wizard buttons (next &amp; previous) and in the last step action buttons like save etc</li>
  </ul>
  <p>The steps are dynamic. Based on some business logic like user's inputs from previous steps.</p>
  <p><em>My current implementation:</em><br />
  I will show only the part where I am using the <code>ComponentFactoryResolver</code> to make it understandable and readable :)</p>
  <pre><code>export class WizComponent implements OnInit { 
      
    public wizContentItems: WizContentItem[] = undefined;
    public currentContentItem: WizContentItem = undefined;
    public currentContentItemNumber: number  = -1;
  
    public currentWizContentComponent: WizContentComponent = undefined;
  
    private componentRef: any;
  
    @Output() public onStepChanged = new EventEmitter&lt;StepPosition&gt;();
  
    private _position: StepPosition = StepPosition.First;
  
    constructor(private componentFactoryResolver: ComponentFactoryResolver, private viewContainerRef: ViewContainerRef) { }
  
    public ngOnInit() {
    } 
  
      public onSelectStep(contentItem: WizContentItem) {
          console.log(&quot;step was clicked&quot;);
          console.log(contentItem);
      
          if (this.currentContentItem !== undefined &amp;&amp;
            !this.validateStep(this.currentContentItem)) {
            return;
          }
      
          if (this.currentWizContentComponent !== undefined ) {
            this.currentContentItem.stepProgressStatus = this.currentWizContentComponent.stepProgressStatus;
        }
      
          contentItem.stepState = StepState.Active;
          const componentFactory = this.componentFactoryResolver.resolveComponentFactory(contentItem.component);
      
          this.viewContainerRef.clear();
          this.componentRef = this.viewContainerRef.createComponent(componentFactory);
          (&lt;WizContentComponent&gt;this.componentRef.instance).data = contentItem.data;
          (&lt;WizContentComponent&gt;this.componentRef.instance).stepState = contentItem.stepState;
      
          this.currentWizContentComponent = (&lt;WizContentComponent&gt;this.componentRef.instance);
      
          if (this.currentContentItem != null) {
            this.currentContentItem.stepState = StepState.Empty;
          }
      
          this.currentContentItem = contentItem;
          this.currentContentItem.stepState = StepState.Active;
      
          // Get currentContentItemNumber based currentContentItem
          this.currentContentItemNumber = this.wizContentItems.findIndex(wizContentItem =&gt; wizContentItem === this.currentContentItem);
      
          this.stepChanged();
        }
  
     public onNextClick(event: Event) {
  
      if ((this.currentContentItemNumber + 1) &lt; this.wizContentItems.length) {
        let nextContentItem = this.wizContentItems[this.currentContentItemNumber + 1];
        if (nextContentItem.stepState === StepState.Disabled) {
          nextContentItem = this.getNextActiveItem(this.currentContentItemNumber + 1);
        }
        if (nextContentItem != null) {
          this.onSelectStep(nextContentItem);
        }
      }
    }
  
    public onPreviousClick(event: Event) {
      if ((this.currentContentItemNumber - 1) &gt;= 0) {
        let previousContentItem = this.wizContentItems[this.currentContentItemNumber - 1];
        if (previousContentItem.stepState === StepState.Disabled) {
          previousContentItem = this.getPreviousActiveItem(this.currentContentItemNumber - 1);
        }
        if (previousContentItem !== null) {
          this.onSelectStep(previousContentItem);
        }
      }
    }
  
    public getCurrentStepPosition(): StepPosition {
      return this._position;
    }
  
    private validateStep(contentItem: WizContentItem): boolean {
      return (&lt;WizContentImplComponent&gt;this.componentRef.instance).isValid();
    }
  
    private stepChanged(): void {
  
      this._position = undefined;
      if (this.currentContentItemNumber &lt;= 0) {
        this._position = StepPosition.First;
      } else if (this.currentContentItemNumber &gt;= this.wizContentItems.length) {
        this._position = StepPosition.Last;
      } else {
        this._position = StepPosition.Middle;
      }
  
      if ((&lt;WizContentComponent&gt;this.componentRef.instance).isSummary) {
        this._position = StepPosition.Summary;
      }
      this.onStepChanged.emit(this._position);
    }
  
    private getNextActiveItem(itemNumber: number): WizContentItem {
  
      if (this.wizContentItems.length &lt;= (itemNumber + 1)) {
        return null;
      }
  
      let nextContentItem = null;
      for (let i = (itemNumber); i &lt; this.wizContentItems.length; i++) {
        if ( this.wizContentItems[i].stepState !== StepState.Disabled ) {
          nextContentItem = this.wizContentItems[i];
          break;
        }
      }
  
      return nextContentItem;
    }
  
    private getPreviousActiveItem(itemNumber: number): WizContentItem {
      if ((itemNumber - 1) &lt; 0 ) {
        return null;
      }
  
      let previousContentItem = null;
      for (let i = (itemNumber - 1); i &gt;= 0; i--) {
        if ( this.wizContentItems[i].stepState !== StepState.Disabled ) {
          previousContentItem = this.wizContentItems[i];
          break;
        }
      }
  
      return previousContentItem;
    }
  }
  </code></pre>
  <p>Thank you!!</p>