首页 > 解决方案 > 检测动态组件上的数据更改不起作用

问题描述

我正在使用动态组件,我按照本教程进行操作并且工作正常。

这是我的实现

动态组件.directive.ts

import { Directive, ViewContainerRef } from '@angular/core';    
@Directive({
    selector: '[DynamicComponent]'
})
export class DynamicComponentDirective {
    constructor(public viewContainerRef: ViewContainerRef) { }
}

而且,这就是创建动态组件的逻辑。它可以检测何时发出数据@Output 这是代码

import { Component, ComponentFactoryResolver, ComponentRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
import { DynamicComponentDirective } from './dynamic-component.directive';
import { DynamicComponentInterface } from '@interfaces/dynamic-component.interface';

@Component({
    selector: 'dynamic-component',
    template: '<ng-template DynamicComponent></ng-template>'
})
export class DynamicComponent implements OnInit, OnDestroy, OnChanges {

    @Input() component!: DynamicComponentInterface;
    @Output() sentData: EventEmitter<any> = new EventEmitter<any>();

    @ViewChild(DynamicComponentDirective, { static: true })
    directive!: DynamicComponentDirective;
    componentRef!: ComponentRef<DynamicComponentInterface>;
    constructor(
    private factoryResolver: ComponentFactoryResolver
    ) { }

    ngOnInit(): void {
    if ( this.component ) {
        this.loadComponent();
    }
    }

    ngOnDestroy(): void {
    this.componentRef.destroy();
    }

    ngOnChanges( changes: SimpleChanges ): void {
    console.log( changes );
    }



    loadComponent(): void {


    const componentFactory = this.factoryResolver
    .resolveComponentFactory( this.component.component );


    const containerRef = this.directive.viewContainerRef;

    this.componentRef = containerRef
    .createComponent<DynamicComponentInterface>( componentFactory );


    this.componentRef.instance.data = this.component.data;
    this.componentRef.instance.emitter?.
    subscribe( (values: any) => this.sentData.emit( values ) );
    this.componentRef.changeDetectorRef.detectChanges();
    }
}

一切正常,这就是我的工作方式......

app.component.html

<mat-accordion [multi]="true">
    <mat-expansion-panel *ngFor="let expansion of salaryPanelRight" [expanded]="true">
    <mat-expansion-panel-header>
        {{ expansion.title }}
    </mat-expansion-panel-header>

    <dynamic-component [component]="expansion.panel"></dynamic-component>
    </mat-expansion-panel>
</mat-accordion>

这就是dynamic-component在逻辑文件上构建的方式

import { Component } from '@angular/core';
import { DynamicComponentInterface } from '@interfaces/dynamic-component.interface';
import { PanelJobDetailsComponent } from './components/panel-job-details/panel-job-details.component';
import { PanelSalaryDetailsResumeComponent } from './components/panel-salary-details-resume/panel-salary-details-resume.component';
import { PanelSalaryResumeComponent } from './components/panel-salary-resume/panel-salary-resume.component';

@Component({
    selector: 'app-salary-data',
    templateUrl: './salary-data.component.html',
    styleUrls: ['./salary-data.component.scss']
})
export class SalaryDataComponent {
    salaryPanelRight: SalaryPanel [] = [
    {
        title: $localize`:@@salary-tab-panel-resume-details: Title 1`,
        panel: {
        component: PanelJobDetailsComponent,
        data: {
            hireSchema: null
        }
        },
    },
    {
        title: $localize`:@@salary-tab-panel-resume-salary: Title 2`,
        panel: {
        component: PanelSalaryResumeComponent
        }
    },
    {
        title: $localize`:@@salary-tab-panel-resume-salary-details: Title 3`,
        panel: {
        component: PanelSalaryDetailsResumeComponent
        }
    },
    ];
    constructor() { }

    getValues( input: any ): void {
    const value = input.target.value;
    this.salaryPanelRight[0].panel.data.hireSchema = value;
    }

}

interface SalaryPanel {
    title: string;
    panel: DynamicComponentInterface;
}

例如PanelJobDetailsComponent有这个@Input() hireSchema!: string;,他的 HTML 只是{{ hireSchema }}

当我从父组件更改值时,它没有改变,正是在这部分

      getValues( input: any ): void {
        const value = input.target.value;
        this.salaryPanelRight[0].panel.data.hireSchema = value;
      }

我已阅读并实施ngOnChanges但没有工作,数据没有改变。实际上我也这样做了this.componentRef.changeDetectorRef.detectChanges();,但它不起作用。当我什么console.logngOnChanges没有发生时,即使我从输入中触发了模糊事件来触发新数据。

如何将更改的数据传递给我的实现?

标签: angularangular-material

解决方案


本文解释了为什么ngOnChanges不工作。

为了让您的变更检测工作,您可以在动态组件中创建设置器并changeDetectorRef.markForCheck()从中调用。我不建议使用detectChanges,因为如果使用不小心,它可能会产生比它解决的问题更多的问题


推荐阅读