使用ControlValueAccessor的角度自定义表单控件

时间:2020-09-02 10:39:57

标签: angular validation controls controlvalueaccessor

这不是问题-在这里我提出了一个解决方案,在这里找不到

这里是带有自定义验证的自定义表单控件的示例。该代码不言自明。主要思想是将验证从父组件传递到自定义内部组件,并在提交表单时触发验证。

<app-country fxFlex formControlName="social_country_id"></app-country>

在这里,我们有应用程序国家/地区组件。 html部分并不重要,它是根据情况定制的。

import { Component, forwardRef, Host, Input, OnDestroy, OnInit, Optional, SkipSelf } from '@angular/core';
import {
  ControlValueAccessor,
  FormControl,
  FormGroup,
  FormGroupDirective,
  NG_VALIDATORS,
  NG_VALUE_ACCESSOR,
} from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { UtilsService } from 'src/app/service/utils/utils.service';
import { FormHelper } from 'src/app/shared/FormHelpers';

@Component({
  selector: 'app-country',
  templateUrl: './country.component.html',
  styleUrls: ['./country.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CountryComponent),
      multi: true,
    },
  ],
})
export class CountryComponent extends FormHelper implements OnInit, ControlValueAccessor, OnDestroy {
  @Input() formControlName: string;

  unsubscribe = new Subject<void>();
  countries = [];
  form: FormGroup;
  value = null;
  propagateChange: Function;

  constructor(
    private utilsService: UtilsService,
    @Optional()
    @Host()
    @SkipSelf()
    private controlContainer: FormGroupDirective
  ) {
    super();
  }

  ngOnInit(): void {
    this.loadCountries();
    this.initForm();
    this.setValidatorsFromParentControl();
    this.listenForChanges();
    this.triggerValidationOnParentFormSubmission();
  }

  private triggerValidationOnParentFormSubmission() {
    this.controlContainer.ngSubmit.subscribe(() => {
      this.form.markAllAsTouched();
    });
  }

  private listenForChanges() {
    this.form.valueChanges.subscribe((value) => {
      this.propagateChange(value.country_id);
    });
  }

  private setValidatorsFromParentControl() {
    this.form.controls['country_id'].setValidators(this.controlContainer.form.controls[this.formControlName].validator);
  }

  private initForm() {
    this.form = new FormGroup({
      country_id: new FormControl(this.value),
    });
  }

  writeValue(value: any) {
    this.value = value;
  }

  registerOnChange(fn: Function) {
    this.propagateChange = fn;
  }

  registerOnTouched() {}

  loadCountries() {
    this.utilsService
      .getCountries()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((payload: Array<any>) => {
        this.countries = payload;
      });
  }

  ngOnDestroy() {
    this.unsubscribe.next();
    this.unsubscribe.complete();
  }
}

0 个答案:

没有答案