Indigosoft / ngxd

✨🦊 NgComponentOutlet + Data-Binding + Full Lifecycle = NgxComponentOutlet for Angular 7, 8, 9, 10, 11, 12, 13, 14, 15, 16+
MIT License
318 stars 29 forks source link

ERROR TypeError: Cannot delete property 'xyz' of [object Object] #29

Open ciukstar opened 4 years ago

ciukstar commented 4 years ago

Error when running ngxd under Angular 9:

ERROR TypeError: Cannot delete property 'layout' of [object Object]
    at HostInputAdapter.dispose (ngxd-core.js:183)
    at HostInputAdapter.detach (ngxd-core.js:161)
    at HostAdapter.detachInput (ngxd-core.js:243)
    at NgxComponentOutletAdapterRef.detachHostInput (ngxd-core.js:390)
    at NgxComponentOutletAdapterRef.updateContext (ngxd-core.js:330)
    at NgxComponentOutletDirective.applyContext (ngxd-core.js:770)
    at NgxComponentOutletDirective.createAdapterRef (ngxd-core.js:787)
    at NgxComponentOutletDirective.ngOnChanges (ngxd-core.js:759)
    at NgxComponentOutletDirective.wrapOnChangesHook_inPreviousChangesStorage (core.js:26448)
    at callHook (core.js:3913)

Where 'layout' is part of *ngxComponentOutlet context. Works fine with ngxd running under Angular 8. Environment:

$ ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/

Angular CLI: 9.0.2
Node: 13.1.0
OS: linux x64

Angular: 9.0.1
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.2
@angular-devkit/build-angular     0.900.2
@angular-devkit/build-optimizer   0.900.2
@angular-devkit/build-webpack     0.900.2
@angular-devkit/core              9.0.2
@angular-devkit/schematics        9.0.2
@angular/cdk                      9.0.0
@angular/cli                      9.0.2
@angular/flex-layout              9.0.0-beta.29
@angular/material                 9.0.0
@ngtools/webpack                  9.0.2
@schematics/angular               9.0.2
@schematics/update                0.900.2
rxjs                              6.5.4
typescript                        3.7.5
webpack                           4.41.2
thekiba commented 4 years ago

Thanks for the question. I was in a hurry to upgrade to version 9, and now many tests have failed. I'll fix it asap.

thekiba commented 4 years ago

Please add a missing setter for a dynamic component. You can see that issue in the browser console.

If this solves the problem, please close the issue.

image

ciukstar commented 4 years ago

Nope, the last published version of @ngxd/core@9.0.1 does not resolve my issue. Here is a sample of my component: showcase.component.html:


<mat-accordion>
  <mat-expansion-panel *ngFor="let sc of showcases;let i = index;" [expanded]="i === 0">
    <mat-expansion-panel-header>
      <mat-panel-title>{{sc.name}}</mat-panel-title>
      <mat-panel-description>{{sc.description}}</mat-panel-description>
    </mat-expansion-panel-header>
    <ng-template matExpansionPanelContent>
      <ng-container *ngIf="(components.get(sc.component).context(sc) | async) as ctx; else loading;">
        <ng-container
          *ngxComponentOutlet="components.get(sc.component).component; context: ctx;">
        </ng-container>
      </ng-container>
    </ng-template>
  </mat-expansion-panel>
</mat-accordion>
<ng-template #loading>
  <mat-progress-bar mode="buffer"></mat-progress-bar>
</ng-template>

showcase.component.ts:


import { Component, OnInit, Type } from '@angular/core';
import { KeycloakService } from 'src/app/service/keycloak.service';
import { ChartTemplate } from 'src/app/model/chart-template';
import { ChartTemplateService } from 'src/app/service/chart-template.service';
import { Observable } from 'rxjs';
import { map, filter } from 'rxjs/operators';
import { memoize } from 'lodash';
import { ThemeService } from 'src/app/service/theme.service';
import { ActivatedRoute } from '@angular/router';
import { ComponentRegistryService } from 'src/app/service/component-registry.service';
import { DisplayContext } from 'src/app/model/display-context.enum';

@Component({
  selector: 'app-showcase',
  templateUrl: './showcase.component.html',
  styleUrls: ['./showcase.component.scss']
})
export class ShowcaseComponent implements OnInit {

  components: Map<string, { component: Type<any>; context: (x: ChartTemplate) => Observable<any> }>;
  theme: string;
  showcases: ChartTemplate[];
  displayContexts = DisplayContext;

  constructor(
    private templateSrv: ChartTemplateService,
    private registry: ComponentRegistryService,
    private kc: KeycloakService,
    private themeSrv: ThemeService,
    private route: ActivatedRoute
  ) {
    this.components = this.registry.components;
  }
...
}

The error message is:


core.js:5845 ERROR TypeError: Cannot delete property 'theme' of [object Object]
    at HostInputAdapter.dispose (ngxd-core.js:189)
    at HostInputAdapter.detach (ngxd-core.js:167)
    at HostAdapter.detachInput (ngxd-core.js:249)
    at NgxComponentOutletAdapterRef.detachHostInput (ngxd-core.js:536)
    at NgxComponentOutletAdapterRef.updateContext (ngxd-core.js:476)
    at NgxComponentOutletDirective.applyContext (ngxd-core.js:920)
    at NgxComponentOutletDirective.createAdapterRef (ngxd-core.js:937)
    at NgxComponentOutletDirective.ngOnChanges (ngxd-core.js:909)
    at NgxComponentOutletDirective.wrapOnChangesHook_inPreviousChangesStorage (core.js:26448)
    at callHook (core.js:3913)

The debugger sends me to line 189 of "ngxd-core.js" - "delete this.host[this.name];" - and I have no idea why it is trying to delete a property of my component. It worked great with Angular 8. :

      * @return {?}
     */
    dispose() {
        /** @type {?} */
        const defaultValue = this.host[this.name];
        this.disposed = true;
        this.changes.complete();
        delete this.host[PRIVATE_HOST_INPUT_ADAPTER + this.name];
        if (this.defaultDescriptor) {
            if (this.defaultDescriptor.writable) {
                this.defaultDescriptor.value = defaultValue;
            }
            Object.defineProperty(this.host, this.name, this.defaultDescriptor);
            if (this.defaultDescriptor.set) {
                this.host[this.name] = defaultValue;
            }
        }
        else {
            delete this.host[this.name];
            this.host[this.name] = defaultValue;
        }
    }
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
 */
/** @type {?} */
const PRIVATE_HOST_ADAPTER = PRIVATE_CONTEXT_PREFIX + 'HOST_ADAPTER';
/**
 * @template TComponent
 */
class HostAdapter {
    /**
     * @param {?} host
     */
    constructor(host) {
        this.host = host;
        if (PRIVATE_HOST_ADAPTER in host) {
thekiba commented 4 years ago

Could you please reproduce this issue on StackBlits or GitHub repo?

thekiba commented 4 years ago

@ciukstar could you please check your issue with @ngxd/core@9.0.3? Let me know if all ok or not.

ciukstar commented 4 years ago

Yes, with @ngxd/core@9.0.3 everything is working now as expected. Issue resolved. Thanks a lot!