【问题标题】:Custom component value is not updated with Angular Reactive Form自定义组件值未使用 Angular Reactive Form 更新
【发布时间】:2019-02-22 18:22:07
【问题描述】:

我创建了一个扩展 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);
    }
  }

}

【问题讨论】:

    标签: angular angular-reactive-forms


    【解决方案1】:

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

    我通过添加来修复示例

    this.rdSpinner.valueChanges.subscribe(result => this._onChange(result));
    

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

    新的堆栈闪电战:stackBlitz

    【讨论】:

    • 但是在控制台中我收到警告“看起来您正在使用带有反应形式指令的禁用属性......我们建议使用这种方法来避免'检查后更改'错误。” . @Korfoo 你知道如何解决这个问题吗?
    • 您可以删除 html 中的 [disabled]=disabled,但是您必须在 ngOnInit() 中使用 if (this.disabled) { this.rdSpinner.disable() } 来禁用它。问题是,如果您从自定义组件更改禁用的输入,它不会传播到 rdSpinner,您将不得不使用其他东西来通知您的自定义组件禁用 rdSpinner。
    • 感谢您的更新,我看到接口 ControlValueAccessor 有一个 setDisabledState 方法,我不应该实现这个接口以避免警告消息吗?
    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 2021-10-29
    • 2019-12-26
    • 1970-01-01
    • 2018-06-10
    相关资源
    最近更新 更多