自定义组件值不会使用Angular Reactive Form更新

时间:2019-02-22 10:04:25

标签: angular angular-reactive-forms

我创建了一个自定义输入组件,该组件扩展了primeng spinner组件,但是当我将其与Angular Reactive Form一起使用时,该组件的模型值不会更新。我有stackblitzed个问题,以便于调试。这是我组件的代码:

import {Component, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild} from '@angular/core';
import {ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
import {Spinner} from 'primeng/primeng';

@Component({
  selector: 'rd-spinner',
  template: `
    <p-spinner [formControl]="rdSpinner"
               [step]="step"
               [min]="min"
               [max]="max"
               [placeholder]="placeholder"
               [disabled]="disabled"
               [readonly]="readonly"
               [maxlength]="maxlength"
               [size]="size"
               [tabindex]="tabindex"
               [inputId]="tabindex"
               [type]="type"
               [required]="required"
               [name]="name"
               [inputStyle]="inputStyle"
               [inputStyleClass]="inputStyleClass"></p-spinner>
  `,
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => RdSpinnerComponent),
    multi: true
  }]
})
export class RdSpinnerComponent implements ControlValueAccessor, OnInit {

  @ViewChild(Spinner) private _spinner: Spinner;
  rdSpinner: FormControl;

  // Required to implement interface ControlValueAccessor
  private _onChange : Function = () => {};
  private _onTouched : Function = () => {};

  // Those inputs at given directly to primeng spinner 
  @Input() step: number = 1;
  @Input() min: number;
  @Input() max: number;
  @Input() placeholder: string;
  @Input() disabled: boolean;
  @Input() readonly: boolean;
  @Input() maxlength: number;
  @Input() size: number;
  @Input() tabindex: number;
  @Input() inputId: string;
  @Input() type: string = 'text';
  @Input() required: boolean;
  @Input() name: string;
  @Input() inputStyle: any;
  @Input() inputStyleClass: string;
  @Output() onChange: EventEmitter<any> = new EventEmitter();
  @Output() onFocus: EventEmitter<any> = new EventEmitter();
  @Output() onBlur: EventEmitter<any> = new EventEmitter();

  constructor() {
  }

  ngOnInit() {
    this.rdSpinner = new FormControl();

    if (this._spinner) {
      const origParseValue = this._spinner.parseValue;
      this._spinner.parseValue = (val: string): number => {
        let value: number;

        if (val.trim() === '') {
          value = null;
        }
        else {
          value = origParseValue.call(this._spinner, val);
        }

        return value;
      }
    }
  }

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

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

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

}

1 个答案:

答案 0 :(得分:1)

当原始微调器的值更改其值时,您应该调用_onchange方法。 您可以通过订阅原始组件的valueChanges并在其发出新值时调用this._onChange()来实现。

我通过添加

修复了示例
this.rdSpinner.valueChanges.subscribe(result => this._onChange(result));

作为当前ngOnInit()的最后一行。

新的堆叠闪电战:stackBlitz