解决方案是在指令中使用@output。使用指令中的输出,可以创建父组件可以订阅的偶数发射器。这样,指令就可以将数据传回父组件。在我的例子中,我在将子组件传递给它的指令中创建了一个输出,如下所示:
import { ComponentFactoryResolver, EventEmitter, ComponentRef, Directive, Input, OnChanges, OnInit, Type, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[dynamicField]'
})
export class DynamicFieldDirective implements Field, OnChanges, OnInit {
@Input()
config: FieldConfig;
@Input()
group: FormGroup;
@Output fieldAdded: EventEmitter<any> = new EventEmitter<any>();
component: ComponentRef<Field>;
constructor(
private resolver: ComponentFactoryResolver,
private container: ViewContainerRef
) {}
ngOnChanges() {
if (this.component) {
this.component.instance.config = this.config;
this.component.instance.group = this.group;
}
}
ngOnInit() {
if (!components[this.config.type]) {
const supportedTypes = Object.keys(components).join(', ');
throw new Error(
`Trying to use an unsupported type (${this.config.type}).
Supported types: ${supportedTypes}`
);
}
const component = this.resolver.resolveComponentFactory<Field>(components[this.config.type]);
this.component = this.container.createComponent(component);
this.component.instance.config = this.config;
this.component.instance.group = this.group;
this.fieldAdded.emit(this.component.instance);
}
}
然后,在父组件中,我可以将函数绑定到该指令的输出事件,该指令随后处理传递给它的子组件,如下所示:
@Component({
exportAs: 'dynamicForm',
selector: 'dynamic-form',
styleUrls: ['dynamic-form.component.scss'],
template: `
<form
class="dynamic-form"
[formGroup]="form"
(submit)="handleSubmit($event)">
<ng-container
*ngFor="let field of config;"
dynamicField
[config]="field"
[group]="form"
(fieldAdded) = "addField($event)"
>
</ng-container>
</form>
`
})
export class DynamicFormComponent implements OnChanges, OnInit {
@Input()
config: FieldConfig[] = [];
fields: object = {};
addField(field: any){
this.fields[field.key] = field;
}
此时,父组件有一个this.fields属性,该属性包含所有子组件实例,可以对它们进行处理。