首页 > 解决方案 > 如何在 Angular 中实现 ControlValueAccessor 的子组件中获取 NgControl 触摸状态?

问题描述

我需要在子组件中达到父母 NgControl 触摸状态

// Parent Component Template
<form #myForm="ngForm">
  <app-testing [(ngModel)]="value" name="testing"></app-testing>
  <button (click)="validate()">Validate</button>
</form>

// Parent Component
validate() {
  Object.keys(form.controls).forEach(key => {
    form.controls[key].markAsTouched();
  });
}

// TestingComponent 
@Component({
    selector: 'app-testing',
    templateUrl: 'testing.component.html',
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => TestingComponent),
            multi: true
        },
        {
            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => TestingComponent),
            multi: true
        }
    ]
})
export class TestingComponent implements ControlValueAccessor, Validator {
    validate(control: AbstractControl): ValidationErrors {
        this.isValid = false;
        if (!this.value) {
            return { required: true };
        } else {
            this.isValid = true;
            return null;
        }
    }

    value: number;

    isValid: boolean = false;
    isTouched: boolean = false;

    writeValue(value: number): void {
        this.value = value;
        this.onChange(this.value);
    }

    onChange: (_: any) => void = (_: any) => {};

    onTouched: () => void = () => {};

    registerOnChange(fn: any): void {
        this.onChange = fn;
    }

    registerOnTouched(fn: any): void {
        this.onTouched = fn;
    }

    registerOnValidatorChange(fn: () => void): void {
        this.onChange = fn;
    }
}

测试组件模板如下:

<input
    type="text"
    class="form-control"
    [class.is-invalid]="!isValid && isTouched"
    [(ngModel)]="value"
    (ngModelChange)="onChange(value)"
    (blur)="onTouched(); isTouched = true;"
/>

在此之前我尝试过直接注入

constructor(@Optional() @Self() public ngControl: NgControl) {
  if (this.ngControl != null) {
      this.ngControl.valueAccessor = this;
  }
}

但我仍然无法订阅 ngControl 的触摸状态更改

你会怎么做?我已经用谷歌搜索并找到了使用 touchChanges observable https://stackoverflow.com/a/43381131/9590251扩展 FormControl 的方法,但我可能有更好的方法。

到目前为止我见过的最好的解决方案在这里https://stackoverflow.com/a/44732590/9590251

标签: angular

解决方案


推荐阅读