ValueChanges는 구성 요소의 formControls에 대해 내 보내지 만 자식 구성 요소의 formControl에는 표시되지 않습니까?

Aug 21 2020

내 Angular 앱 내에 몇 가지 다른 formControl을 사용하는 양식이 있습니다. 그들 중 일부는 구성 요소 자체 내에 있고 일부는 첫 번째 구성 요소에서 사용되는 두 번째 구성 요소 내에 있습니다.

자식 구성 요소가 양식의 값을 변경하면 (로깅으로 확인할 수 있음) 관찰 가능한 valueChanges가 방출되지 않는다는 것을 발견했습니다. 그러나 그것은 형태를 바꾸고, 그래서 확실히 observable이 방출하도록해야합니까?

다른 formControls를 포함하는 부모 구성 요소에 formGroup이 있으며 그중 하나 targetGroups는 자식 구성 요소로 직접 전달되어 조작 할 수 있습니다. 이것은 관찰 가능한 valueChanges를 발생시키지 않는 것입니다. 그러나 자식 구성 요소를 사용한 후 양식을 기록하면 예상대로 양식을 조작하고 있음을 알 수 있습니다.

부모 구성 요소

  @Input() alertData: SafeguardAlert;

  form: FormGroup;

  constructor(private formBuilder: FormBuilder) { }

  ngOnInit() {
    this.form = this.formBuilder.group({
      enabled: this.formBuilder.control(this.alertData.enabled),
      frequency: this.formBuilder.control(this.alertData.frequency),
      targetGroups: this.formBuilder.control(this.alertData.targetGroups),
    });

    this.formChange();
  }

  get targetGroups(){
    return this.form.get('targetGroups') as FormControl;
  }

  //TODO :: Temp, remove later
  formChange(){
    this.form.valueChanges.subscribe(res => {
      console.log(res);
    })
  }

부모 템플릿

<div>
  <form [formGroup]="form">
    <mat-expansion-panel>
      <div class="alert-body">
        <div class="width-33 mt-md">
          <mat-form-field>
            <mat-label>
              Alert Frequency
            </mat-label>
            <mat-select [formControlName]="'frequency'">
              <mat-option [value]="'instant'">
                Instant
              </mat-option>
              <mat-option [value]="'daily'">
                Daily
              </mat-option>
            </mat-select>
          </mat-form-field>
        </div>
          <app-alert-chip-list [fControl]="targetGroups"></app-alert-chip-list>
      </div>
    </mat-expansion-panel>
  </form>
</div>

하위 구성 요소


  @Input() fControl: FormControl;

  constructor() { }

  ngOnInit() {
  }

  pushToFormcontrol(value: any) {
    this.formControlArray.push(value);
  }

  get formControlArray(){
    return this.fControl.value as string[];
  }

  spliceFromFormcontrol(index: number){
    this.formControlArray.splice(index, 1);
  }

  clearInput(ref: HTMLInputElement){
    ref.value = "";
  }

자식 템플릿

<div class="card chip-list-padding p-sm">
  <div class="flex-row align-items-center">
    <mat-icon class="ml-sm mr-sm">person</mat-icon>
    <mat-chip-list class="flex-row flex-wrap">
      <div class="mr-sm" *ngFor="let element of formControlArray, let i = index">
        <mat-chip [disableRipple]="true" class="chip" >
          <div>
            <span>{{element}}</span>
            <button type="button" mat-icon-button [disableRipple]="true" (click)="spliceFromFormcontrol(i)">
              <mat-icon>clear</mat-icon>
            </button>
          </div>
        </mat-chip>
      </div>
      <div class="chip-list-input-cont">
        <input #listInput class="chip-list-input"
               (keyup.enter)="pushToFormcontrol(listInput.value); clearInput(listInput);">
      </div>
    </mat-chip-list>
  </div>
</div>

답변

3 SlawaEremin Aug 21 2020 at 17:14

여기에 몇 가지 문제가 있습니다.

  pushToFormcontrol(value: any) {
    this.formControlArray.push(value);
  }

  get formControlArray(){
    return this.fControl.value as string[];
  }

여기에서 컨트롤의 값을 직접 변경했지만 값은 setValue 또는 patchValue를 통해서만 업데이트해야합니다. valueChanges

당신의 코드는

  pushToFormcontrol(value: any) {
    this.fControl.patchValue([...formControlArray, value]);
  }

  get formControlArray(){
    return this.fControl.value as string[];
  }

  spliceFromFormcontrol(index: number){
    this.formControlArray.splice(index, 1);
  }

한 번 더 알림을 받으면 배열 값이 있으면 formArray를 사용하는 것이 좋습니다.

 this.form = this.formBuilder.group({
      enabled: this.formBuilder.control(this.alertData.enabled),
      frequency: this.formBuilder.control(this.alertData.frequency),
      targetGroups: this.formBuilder.array([]),
 });