我有一个主要组件,该组件的窗体嵌入了几个子组件/窗体。
主要组件使用服务将数据重新发送到API服务器。该服务在主组件和子组件中都有我正在听的主题。
主要组件:
@Component({
selector: 'zoomnew',
templateUrl: './zoomnew.component.html',
styleUrls: ['./zoomnew.component.scss']
})
export class ZoomnewComponent implements OnInit, OnDestroy {
@ViewChild(ZoomFooComponent) ZoomFooComp: ZoomFooComponent;
@ViewChild(ZoomBarComponent) ZoomBaromp: ZoomBarComponent;
destroy$: Subject<boolean> = new Subject<boolean>();
mandatObjSubscription: Subscription;
mandatoryObjects: {
...
} = {...};
zoomForm: FormGroup;
constructor(
private zoomService: ZoomService,
) { }
/////////////////////////////////////////////////////////
////// OnInit & onDestroy
/////////////////////////////////////////////////////////
ngOnInit() {
this.initForm();
this.mandatObjSubscription=this.zoomService.mandatObjSubject$.takeUntil(this.destroy$).subscribe(
(data)=> {
this.mandatoryObjects=data;
this.setzoomDflt();
},
);
this.onChanges();
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.unsubscribe()
}
/////////////////////////////////////////////////////////
////// Form Functions
/////////////////////////////////////////////////////////
initForm() {
this.zoomForm = this.formBuilder.group({
foo: new FormControl('', [Validators.required]),
bar: new FormControl('', [Validators.required]),
});
}
setzoomDflt() {
this.zoomForm.patchValue({
foo: this.fooDflt,
bar: this.barDflt,
};
}
我的一个子组件
@Component({
selector: 'ngx-zoom-foo',
templateUrl: './zoom-foo.component.html',
styleUrls: ['./zoom-foo.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ZoomFooComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => ZoomFooComponent),
multi: true
}
]
})
export class ZoomFooComponent implements OnInit, OnDestroy, ControlValueAccessor {
@Input() inEntityName: string;
@Input() inErrors: any[];
@ViewChild(ZoomFoolineComponent) FoolineComp: ZoomFoolineComponent;
entityName: string;
foos: Foo[];
destroy$: Subject<boolean> = new Subject<boolean>();
mandatObjSubscription: Subscription;
zoomFooForm: FormGroup;
constructor(
private formBuilder: FormBuilder,
private zoomService: ZoomService,
) { }
/////////////////////////////////////////////////////////
////// OnInit & onDestroy
/////////////////////////////////////////////////////////
ngOnInit(): void {
this.entityName= this.inEntityName;
this.initForm();
this.mandatObjSubscription=this.zoomService.mandatObjSubject$.takeUntil(this.destroy$).subscribe(
objects => {
this.foos=objects[this.entityName.toLowerCase()+'s'];
}
);
this.zoomFooForm.valueChanges.takeUntil(this.destroy$).subscribe(value => {
this.onChange(value);
this.onTouched();
});
this.zoomService.emitMandatoryObjects();
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.unsubscribe();
}
//////////////////////////////////////////////////////////////////////////////
/////* Control Value Accessor
//////////////////////////////////////////////////////////////////////////////
get value(): Fooline[] {
return this.zoomFooForm.value;
}
set value(value: Fooline[]) {
//if( value !== undefined && this.value !== value){
if( value !== undefined ){
this.getFoolines().clear();
this.foos.forEach(foo => {
const Entry = (value.find(item => item.id == foo.id))? value.find(item => item.id == foo.id): null;
this.onAddFooline({
id: foo.id,
selected: (Entry)? Entry.selected : foo.bydefault,
param: (Entry)? Entry.param : '',
foo: foo,
})
})
this.onChange(value);
this.onTouched();
}
}
onChange: any = () => {}
onTouched: any = () => {}
// this method sets the value programmatically
writeValue(value: Fooline[]) {
if (value) {
this.value = value;
}
if (value === null) {
this.zoomFooForm.reset();
}
}
// upon UI element value changes, this method gets triggered
registerOnChange(fn) {
this.onChange = fn;
}
// upon touching the element, this method gets triggered
registerOnTouched(fn) {
this.onTouched = fn;
}
// communicate the inner form validation to the parent form
validate(_: FormControl) {
return this.zoomFooForm.valid ? null : { profile: { valid: false } };
}
get errors() {
return this.zoomFooForm.errors ? null : this.zoomFooForm.errors;
}
//////////////////////////////////////////////////////////////////////////////
/////* Form Functions
//////////////////////////////////////////////////////////////////////////////
get f() { return this.zoomFooForm.controls; }
initForm() {
this.zoomFooForm = this.formBuilder.group({
foolines: this.formBuilder.array([]),
});
}
/////////////////////////////////////////////////////////
////// Gestion des add / remove fooline
/////////////////////////////////////////////////////////
get foolines() {
return this.zoomFooForm.get('foolines') as FormArray;
}
getFoolines(): FormArray {
return this.zoomFooForm.get('foolines') as FormArray;
}
onAddFooline(foo) {
this.getFoolines().push(this.formBuilder.control(foo, Validators.required));
}
onDelFooline(event) {
this.getFoolines().removeAt(event.currentTarget.id);
}
}
和HTML 主要
<ngx-zoom-foo id="fooComp" formControlName="foo"
inEntityName="foo" [inErrors]="">
</ngx-zoom-foo>
子组件
<ng-container formArrayName="foolines"
*ngFor="let ctr of foolines.controls; let i=index">
<ngx-zoom-fooline id="foo_{{ i }}" [formControlName]="i" //ERROR HERE
[inEntityName]="foo" [inErrors]="ctr.errors">
</ngx-zoom-fooline>
</ng-container>
但是我收到一个错误:ExpressionChangedAfterItHaHasBeenCheckedError
感谢您的帮助