【问题标题】:Angular 4 - Circular dependency detected. Two components have the other component's .ts file importedAngular 4 - 检测到循环依赖。两个组件导入了另一个组件的 .ts 文件
【发布时间】:2018-07-02 17:17:48
【问题描述】:

目前正在解决我们代码库中引入的循环依赖项。我们的团队使用 webpack 循环依赖插件,因此如果找到这些循环依赖项之一,我们会在浏览器控制台中收到通知。

浏览器控制台中的错误内容如下: 检测到循环依赖: src\app\domain\admin\employer\employer-form\employer-form.component.ts -> src\app\domain\admin\people\people-form\people-form.component.ts -> > src\app\domain\admin\people\people-form\demographics-form\demographics-form.component.ts -> src\app\domain\admin\employer\employer-form\employer-form.component.ts

employer-form.component.ts 的相关部分

import { PanelTypesEnum } from '../../core/enums/panel-types.enum';
import { PeopleFormComponent } from '../../people/people-form/people-form.component';
import { PeopleService } from '../../people/people.service';

@Component({
    selector: 'hl2-employer-form',
    templateUrl: 'employer-form.component.html',
    styleUrls: ['employer-form.component.scss']
})

export class EmployerFormComponent extends BaseComponentService implements OnInit, OnDestroy {
    @Input() model: PanelModel;
    ...

     constructor(route: ActivatedRoute,
            ...) {
    super(route);
}

    ngOnInit() {
        this.initializeForm();
        this.componentInitialize();
        this.initializeSubscriptions();
    }


    confirmCancel(): void {
        if (!this.employerForm.pristine || this.employerForm.dirty) {
            this.adminConfirmationService.confirm(this.confirmation);
        } else {
            this.navigateAwayFromForm();
        }
    }

    componentInitialize(): void {
        this.confirmation = {message: '', accept: () => { this.navigateAwayFromForm(); }};
        this.panelService.onPanelHide.takeUntil(this.ngUnsubscribe)
            .subscribe(panel => {
                if (panel && panel.id === this.model.id) {
                    this.confirmCancel();
                } else if (this.panelService.verifyEditFormPanelRequiresConfirmation(this.model, panel)) {
                    this.confirmation.databag = <PanelModel>panel;
                    this.confirmCancel();
                } else {
                    this.navigateAwayFromForm();
                }
            });
    }

    navigateAwayFromForm(): void {
        let panel: PanelModel;
        this.employerForm.reset('');
        this.panelService.removePanel(this.model);

        // in the case this form was activated by people form, only allow the user to navigate back to the people form on cancel, or pill click.
        if (this.model.options.activatorPanel === <Component>PeopleFormComponent) {
            if (this.peopleService.person.getValue().peopleId) {
                // need to check current person in peopleService to determine if there is
                // a peopleId assigned. If so, we need to redirect the user back to edit people form.
                this.adminPanelService.newPeoplePanel(PanelTypesEnum.EditPeople, <Component>PeopleFormComponent,
                    <Component>EmployerFormComponent, false);
            } else {
                this.adminPanelService.newPeoplePanel(PanelTypesEnum.CreatePeople, <Component>PeopleFormComponent,
                    <Component>EmployerFormComponent, false);
            }
            return;
        }

        // otherwise, set next panel onFormClosed
        if (this.confirmation.databag instanceof PanelModel) {
            panel = this.confirmation.databag;
        } else {
            panel = this.adminPanelService.getEmployerGridPanel();
        }
        this.panelService.onFormClosed.next(panel);
    }
 ....

people-form.component.ts 的相关部分

import { EmployerFormComponent } from '../../employer/employer-form/employer-form.component';
import { DisplayDateTimePipe } from 'shared/date.pipe';
import { PeopleConstants } from '../../core/constants/people-constants';

@Component({
    selector: 'hl2-people-form',
    templateUrl: './people-form.component.html',
    styleUrls: ['./people-form.component.scss']
})

export class PeopleFormComponent extends BaseComponentService implements OnInit, OnDestroy {
    @Input() model: PanelModel;
    @ViewChild(DemographicsFormComponent) demographicsFormComponent: DemographicsFormComponent;

   ...
   ...

    showEmployerGrid: BehaviorSubject<boolean> = new BehaviorSubject(false);

    constructor(route: ActivatedRoute,
                ...) {
        super(route);
    }

    ngOnInit(): void {
        this.componentInitialize();
        this.initializeForm();
        this.initializeSubscriptions();
    }

public initializeForm(): void {
    if (this.model.options.activatorPanel === <Component>EmployerFormComponent) {
        this.showEmployerGrid.next(true);
    }

    this.peopleForm = PeopleFormUtils.newPeopleForm(this.formBuilder);

    this.nameTypeOptions = AdminConstants.nameTypeOptions();
    this.prefixOptions = AdminConstants.prefixOptions();
    this.suffixOptions = AdminConstants.suffixOptions();
    this.professionalSuffixOptions = AdminConstants.professionalSuffixOptions();

    this.genderOptions = PeopleFormUtils.translateGenderOptions(this.translateService);
    this.maritalOptions = AdminConstants.maritalStatusOptions();
    this.languageOptions = AdminConstants.languageOptions();
    this.races = AdminConstants.metaDataList.races;
    this.ethnicities = AdminConstants.metaDataList.ethnicities;
}
    navigateAwayFromForm(): void {
        let panel: PanelModel;
        this.demographicsFormComponent.demographicsForm.reset('');
        this.panelService.removePanel(this.model);

        // in the case this form was activated by user form, only allow the user to navigate back to the user form on cancel, or pill click.
        if (this.model.options.activatorPanel === <Component>UserFormComponent) {
            // override default requireConfirmation setting, since this is reopening the people grid modal within the user form.
            this.adminPanelService.newUserPanel(PanelTypesEnum.CreateUser, <Component>UserFormComponent, <Component>PeopleFormComponent, false);
            return;
        }

        // otherwise, set next panel onFormClosed
        if (this.confirmation.databag instanceof PanelModel) {
            panel = this.confirmation.databag;
        } else {
            panel = this.adminPanelService.getPeopleGridPanel();
        }
        this.panelService.onFormClosed.next(panel);
    }

    componentInitialize(): void {
        this.confirmation = {
            message: '', accept: () => {
                this.navigateAwayFromForm();
            }
        };
        this.panelService.onPanelHide.takeUntil(this.ngUnsubscribe)
            .subscribe((panel) => {
                //probably x click from pill
                if (panel && panel.id === this.model.id) {
                    this.confirmCancel();
                } else if (this.panelService.verifyEditFormPanelRequiresConfirmation(this.model, panel)) {
                    this.confirmation.databag = <PanelModel>panel;
                    if (this.areFormsDirty()) {
                        this.confirmCancel();
                    } else {
                        this.navigateAwayFromForm();
                    }
                }
            });
    }

由于两个组件在导入语句中导入了另一个组件的文件,我们看到了循环依赖警告。

有人对如何解决这个问题有什么建议?提前致谢!

【问题讨论】:

    标签: javascript angular dependency-injection ecmascript-6 es6-modules


    【解决方案1】:

    我没有给你具体的答案,但显然问题出在 people-form.component 中的 initializeForm() 方法的第一行:

    if (this.model.options.activatorPanel === <Component>EmployerFormComponent)
    

    我建议您对代码进行结构化,以便 PeopleFormComponent 不需要明确了解 EmployerFormComponent。

    执行此操作的一种方法是确定是否需要在其他地方显示雇主网格,然后可能将布尔值传递到路由中,或者注入具有该信息的共享服务。

    我也不确定您当前的检查是否有效,因为您将 EmployerFormComponent 显式转换为组件。也许您只需要检查 this.model.options.activatorPanel 是否为非空?

    如果您确实需要显式检查,请创建一个接口,然后让 EmployerFormComponent 实现该接口。然后检查“model.options.activatorPanel”是否实现了该接口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-25
      • 1970-01-01
      • 2018-06-28
      • 1970-01-01
      • 2016-08-16
      • 1970-01-01
      相关资源
      最近更新 更多