Uncaught (in promise): TypeError: Cannot read property 'ɵcmp' of undefined in angular 10

Viewed 7676

I am getting this error Uncaught (in promise): TypeError: Cannot read property 'ɵcmp' of undefined in angular when trying to load the app I just compiled with --prod flag with both optimization and buildOptimizer set as true, when I set both to false the issue disappear and application is loading without issues but the application size is bigger and performance isn't as expected, I need to build a production with both optimization and buildOptimizer set as true, anyone have a good solution to this issue?

angular.json file :

            "staging": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.staging.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }

My Code in .ts to load dynamic component and this part not work when production angular application and have pervious error :

//Directive created
  @ViewChild(RequestsDirective) tabHost: RequestsDirective;

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private viewContainerRef: ViewContainerRef,
    public requestsMainService: RequestsMainService,
    private spinner: NgxSpinnerService) { }

  ngOnInit(): void { }

  // Load Component in ng template  and set request name in services and hide category - request type part
  async loadTabComponent(_requestid: number, _requestname: string) {
    //debugger;
    // to set request name dynamic in all requests
    this.requestsMainService.RequestName = _requestname;
    // Hide Category And Requests type
    $('#div_main').hide('slow');

    // Search in App Model about component name
    const factories = Array.from( 
        this.componentFactoryResolver['ngModule']
            .instance.constructor.ɵmod.declarations
    );
    const factoryClass = factories.find(
        (x: any) => x.name === ('Request1Component')
    ) as Type<any>;

    // clear any previous component
    this.viewContainerRef.detach();
    this.viewContainerRef.clear();
    // get dynamic component by name
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(factoryClass);
    // load it in ng template
    this.viewContainerRef = this.tabHost.viewContainerRef;
    this.viewContainerRef.createComponent(componentFactory);
  }

Note

Request1Component this name of component I want to load it dynamic

1 Answers

this issue happens when you try to create/add/attach an undefined component to an existing component ref

change this line:

this.viewContainerRef.createComponent(componentFactory);

to this:

if (factoryClass != undefined) this.viewContainerRef.createComponent(factoryClass);

*note 1:

you don't need to use componentFactoryResolver.resolveComponentFactory() for createComponent() anymore it is deprecated, you should simply pass the class reference directly to createComponent()

*note 2:

when passing a value to viewContainerRef.createComponent() always check if it is undefined if it is not (maybe the class was not registered or created yet) - then don't add it, or replace it with some place holder component

Related