【问题标题】:Angular 8.2 Shared component that extends another component throws No component factory error扩展另一个组件的Angular 8.2共享组件抛出没有组件工厂错误
【发布时间】:2020-12-23 01:41:18
【问题描述】:

我目前正在对应用程序进行一些重构,即某些表单。 我注意到他们都很相似。在重构之前他们正在工作,但是当我添加新的 parent 类并对其进行扩展时,我开始为子组件收到此错误:

ERROR 错误:未找到 SaveCategoryComponent 的组件工厂。你把它添加到@NgModule.entryComponents 了吗?

我的 组件如下所示:

import { OnInit, Inject } from '@angular/core';
import { FormGroup } from '@angular/forms';

import { BaseModel, Attempt } from '@models';
import { NotificationService } from 'src/app/_shared/notification/notification.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { Observable } from 'rxjs';

export class SaveComponent implements OnInit {
    public formGroup: FormGroup;
    public submitted: boolean;
    public notifications: object;
    public isEditing: boolean;

    // convenience getter for easy access to form fields
    get f() {
        return this.formGroup.controls;
    }

    constructor(
        @Inject(MAT_DIALOG_DATA) public model: BaseModel,
        public dialogRef: MatDialogRef<any>,
        public notificationService: NotificationService,
    ) {}

    ngOnInit(): void {
        this.isEditing = !!this.model.id;
    }

    public onSave(callback: (model: any) => Observable<any>) {
        this.submitted = true;

        if (this.formGroup.valid) {
            callback(this.formGroup.value).subscribe(
                (response: Attempt<BaseModel>) => {
                    if (response.failure) {
                        this.notificationService.show(`${response.error.message}`, 'danger');
                    } else {
                        this.notificationService.show(`Successfully saved your category.`, 'success');
                        this.formGroup.reset();
                    }

                    this.submitted = false;
                    this.dialogRef.close(response.result);
                },
                () => {
                    this.submitted = false;
                },
            );
        }
    }
}

如您所见,它正在寻找一些数据,在这种情况下为BaseModel

export interface BaseModel {
    id: string | number;
}

我的类别看起来像这样:

import { BaseModel } from './base-model';

export class Category implements BaseModel {
    id: string;
    name: string;
    image: string;
    active: boolean;
}

所有这些都编译并看起来很好。 然后我有 child,它看起来像这样:

import { Component, OnInit, Inject } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { SaveComponent } from '../save.component';

import { Category } from '@models';
import { CategoryService } from '@services';
import { NotificationService } from '../../notification/notification.service';

@Component({
    selector: 'app-save-category',
    templateUrl: './save-category.component.html',
    styleUrls: ['./save-category.component.scss'],
})
export class SaveCategoryComponent extends SaveComponent implements OnInit {
    constructor(
        @Inject(MAT_DIALOG_DATA) public model: Category,
        public dialogRef: MatDialogRef<SaveCategoryComponent>,
        public notificationService: NotificationService,

        private formBuilder: FormBuilder,
        private categoryService: CategoryService,
    ) {
        super(model, dialogRef, notificationService);
    }

    ngOnInit(): void {
        this.formGroup = this.formBuilder.group({
            id: [this.model.id, Validators.required],
            name: [this.model.name, Validators.required],
            image: [this.model.image],
            active: [this.model.active],
        });
        super.ngOnInit();
    }

    public save() {
        const method = this.isEditing ? 'update' : 'create';
        this.onSave(this.categoryService[method]);
    }
}

这是我的共享模块的一部分,被声明导出并添加为entryComponent

@NgModule({
    imports: [
        CommonModule,
        ReactiveFormsModule,
        RouterModule,
        FormsModule,           

        MatAutocompleteModule,
        MatButtonModule,
        MatCardModule,
        MatDialogModule,
        MatFormFieldModule,
        MatIconModule,
        MatInputModule,
        MatRadioModule,
    ],
    declarations: [
        AlertDialogComponent,
        ConfirmationDialogComponent,
        SaveBrandComponent,
        SaveCategoryComponent,
    ],
    exports: [
        AlertDialogComponent,
        ConfirmationDialogComponent,
        SaveBrandComponent,
        SaveCategoryComponent,
    ],
    providers: [DecimalPipe],
    entryComponents: [
        NotificationComponent,
        UploadImagesComponent,

        AlertDialogComponent,
        ConfirmationDialogComponent,
        SaveBrandComponent,
        SaveCategoryComponent,
    ],
})
export class SharedModule {}

(我已经从模块中删除了任何完全不相关的代码) 我还创建了一个对话服务(在创建 parent 之前它正在工作:

import { Injectable } from '@angular/core';

import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';

@Injectable({
    providedIn: 'root',
})
export class DialogService {
    constructor(private dialog: MatDialog) {}

    public open(component: any, model: any): MatDialogRef<any> {
        const dialogConfig = new MatDialogConfig();

        dialogConfig.disableClose = true;
        dialogConfig.autoFocus = true;
        dialogConfig.data = model;

        return this.dialog.open(component, dialogConfig);
    }
}

然后在我的主要组件中,我执行以下操作:

openEditModal(model: Category) {
    const modalRef = this.dialogService.open(SaveCategoryComponent, model);

    modalRef.afterClosed().subscribe((result: Category) => {
        if (result) {
            this.updateItem(result);
            this.notificationSvc.show('You have successfully updated ' + result.name);
        }
    });
}

在我创建 SaveComponent 之前,这一切都在起作用。一旦我尝试扩展它,我就会收到上面的错误。我知道组件 is 在共享模块的 entryComponents 中定义,所以我不知道它在抱怨什么。

谁能帮忙?

【问题讨论】:

  • 您是否也尝试将SaveComponent 添加到入口组件数组中?就像冰雹玛丽一样,我可以看到由于错误而可能需要这样做并在错误消息中被掩盖。 exportsdeclarations 的任意组合也一样
  • 我不能,因为它没有 @component 装饰器 :(
  • 嗯,我在某处读到(不要问我在哪里),在组件继承中 @Component 装饰器被合并在一起(来自子级的字段覆盖父级的字段)。我认为您可以安全地添加该装饰器并覆盖这些值,甚至可能需要它才能正常运行。
  • 我会试一试,但我很确定你不能:) 坚持住,我会报告!
  • 我搜索了“组件继承 Angular”,前 3 个相关结果都在其基础组件上使用了 @Component 装饰器,例如 here。他们提供虚拟模板和样式,并覆盖子项中的那些。希望它与您的问题有关

标签: angular


【解决方案1】:

我花了好几个小时解决这个问题。然后我发现一个帖子提到 Angular 9 中没有使用 entryComponents,所以我按照这个指南更新了我所有的包:

https://update.angular.io/

当我这样做时,我开始收到新的错误。 我经历了这一切,最终我发现我的AppModule 需要同时导入FormsModuleReactiveFormsModule。当我这样做时,一切都开始工作了。

为了科学,我决定回到我原来的分支并尝试导入这些模块,看看这是否解决了 8.2 中的问题。它确实没有,所以我不知道如何修复它。 我找到的唯一解决方案是升级:(

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    相关资源
    最近更新 更多