You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular14问题:删除FormArray项后剩余项值被清空

问题原因

你的StylingInputComponent同时执行了两种冲突的表单逻辑:
一方面通过@Input()接收外部传入的FormGroup实例,直接操作父组件的表单结构;另一方面又实现了ControlValueAccessor接口,将自身注册为独立的表单控件。当删除FormArray项时,StylingForm.valueChanges触发并调用registerOnChange中的回调,Angular表单系统会误判组件值发生变化,进而触发反向的writeValue调用,而writeValue里的setValue操作会错误覆盖剩余表单组的值,最终导致数据清空。

解决方法

移除ControlValueAccessor相关实现即可,因为你的场景是直接操作外部传入的FormGroup,不需要将组件封装为独立表单控件。

修改后的styling-input.component.ts代码:

@Component({
  selector: 'styling-input',
  templateUrl: './styling-input.component.html',
  styleUrls: ['./styling-input.component.css']
  // 移除NG_VALUE_ACCESSOR的providers配置
})
export class StylingInputComponent { // 移除ControlValueAccessor接口实现

  @Input() StylingForm!: FormGroup<StylingParams>;
  
  get MediaQueryList() {
    return this.StylingForm.get('mediaQueries') as FormArray<FormGroup<MediaQueryParams>>;
  }

  // 移除writeValue、registerOnChange、registerOnTouched三个方法

  private createMediaQueryGroup(): FormGroup<MediaQueryParams> {
    return new FormGroup<MediaQueryParams>({
      selectorParams: new FormGroup<MediaSelectorParams>({
        mediaType: new FormControl<MediaTypeParams>('all'),
        expressions: new FormArray<FormGroup<MediaExpressionGroupParams>>([]),
      }),
      rules: new FormControl<string>('')
    });
  }

  public addMediaQuery():void{
    this.MediaQueryList.push(this.createMediaQueryGroup());
  }

  public removeMediaQuery(item: number): void{
    this.MediaQueryList.removeAt(item);
  }
}

逻辑说明

ControlValueAccessor的作用是将自定义组件封装为独立表单控件(如原生input、select),使其能与formControl等指令配合使用。而你的场景是将父组件的FormGroup拆分到子组件中进行操作,本质是共享同一个表单实例,两种模式不能混用,否则会触发表单系统的双向更新冲突,导致数据异常。

内容的提问来源于stack exchange,提问作者Optiq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 12:24:19