简体   繁体   English

Angular 14:从FormArray中删除项目会清除剩余项目的值

[英]Angular 14: deleting items from FormArray clears the values of remaining items

I created a form using custom inputs and ControlValueAccessor which you can see here .我使用自定义输入和ControlValueAccessor创建了一个表单,您可以在此处看到。 After finally getting it to work I noticed whenever I delete an item from a FormArray it clears the values of the other FormGroups still present in the array.在终于让它工作之后,我注意到每当我从FormArray中删除一个项目时,它都会清除数组中仍然存在的其他FormGroups的值。 If you run the demo and click on the add-media-query button a couple times and fill one out then delete one of the others you'll see what I mean.如果您运行演示并单击add-media-query按钮几次并填写一个然后删除其他一个,您会明白我的意思。 The code bellow is an example of how I have everything set up.下面的代码是我如何设置所有内容的示例。

The form表格

SvgForm : FormGroup<SvgForm> = new FormGroup<SvgForm>({
    title: new FormControl<string>(''),
    graphicId: new FormControl<string>(''),
    svgInput : new FormControl<string>(''),
    viewBox : new FormGroup<ViewBoxParams>({
      x: new FormControl<string>(''),
      y: new FormControl<string>(''),
      width: new FormControl<string>(''),
      height: new FormControl<string>('')
    }),
    styling: new FormGroup<StylingParams>({
      globalStyles: new FormControl<string>(''),
      mediaQueries: new FormArray<FormGroup<MediaQueryParams>>([])
    })
  });

Inside the template I pass the styling FormGroup into a custom component called styling-input through an @Input() like so在模板中,我通过@Input()styling FormGroup 传递给一个名为styling-input输入的自定义组件,如下所示

<styling-input [StylingForm]="SvgForm.controls.styling"></styling-input>

This is how the styling-input is set up.这就是styling-input的设置方式。

styling-input.component.ts样式输入.component.ts

@Component({
  selector: 'styling-input',
  templateUrl: './styling-input.component.html',
  styleUrls: ['./styling-input.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: StylingInputComponent,
      multi: true
    }
  ]
})
export class StylingInputComponent implements ControlValueAccessor{

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

  writeValue(value: any){ if(value){ this.StylingForm.setValue(value); } }

  registerOnChange(fn: any){ this.StylingForm.valueChanges.subscribe(fn); }

  registerOnTouched(onTouched: Function){}

  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);
  }

}

Then inside the template I iterate over the MediaQueryList getter like this然后在模板中我像这样遍历MediaQueryList getter

<article formArrayName="mediaQueries">

  <media-query-input *ngFor="let a of MediaQueryList.controls; let i = index"
    [MediaQueryForm]="a"
    [attr.GroupId]="i"
    (RemoveGroup)="removeMediaQuery($any($event))"
  ></media-query-input>

</article>

The property MediaQueryForm is an @Input() that I pass the FormGroup into and the i variable is passed back up through the RemoveGroup Output once a delete button is pushed and you can see in the code above the removeMediaQuery() function uses removeAt() on the MediaQueryList .属性MediaQueryForm是一个@Input() ,我将FormGroup传递到其中,一旦按下delete按钮, i变量就会通过RemoveGroup Output 向上传递,您可以在上面的代码中看到removeMediaQuery() function 使用removeAt()MediaQueryList上。

I haven't really tried anything different as this is the suggested way to remove an element from a FormArray , however due to me using ControlValueAccessor I'm guessing there may be some other things going on under the hood that I'm not aware of.我没有真正尝试过任何不同的事情,因为这是从FormArray中删除元素的建议方法,但是由于我使用ControlValueAccessor我猜可能还有其他一些我不知道的事情发生在幕后. Does anybody know why this happens and how to fix it?有谁知道为什么会发生这种情况以及如何解决它?

You are not passing GroupId input value to the media-query-input component.您没有将GroupId输入值传递给 media-query-input 组件。

Instead of setting attribute value pass input using without attr prefix.而不是使用不带 attr 前缀的方式设置属性值传递输入。

[attr.GroupId]="i" ===> [GroupId]="i"

styling.input.component样式.输入.组件

 <media-query-input *ngFor="let a of MediaQueryList.controls; let i = index"
        [MediaQueryForm]="a"
        [GroupId]="i"
        (RemoveGroup)="removeMediaQuery($any($event))" >
 </media-query-input>

Forked Example 分叉示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM