【问题标题】:angular custom input component not updating角度自定义输入组件未更新
【发布时间】:2019-02-25 05:32:39
【问题描述】:

我多次创建了自定义输入组件。我可以成功设置 [(ngModel)] 接收到的初始值,但是没有处理对输入字段的任何更改。 更准确地说:writeValue 最初会被调用,而 setter 不会。

组件如下所示:

@Component({
  selector: 'app-timepicker',
  templateUrl: './timepicker.component.html',
  styleUrls: ['./timepicker.component.scss'],
  providers: [{provide: MatFormFieldControl, useExisting: forwardRef(() => NexupTimepickerComponent)}]
})
export class NexupTimepickerComponent implements OnDestroy, ControlValueAccessor {

  autofilled: boolean;

  // Subject for the changes on the input
  stateChanges = new Subject<void>();

  // Grouping of the input fields
  parts: FormGroup;

  public _onChange: any;

  constructor(fb: FormBuilder, private fm: FocusMonitor, private elRef: ElementRef<HTMLElement>,
              @Optional() @Self() public ngControl: NgControl
  ) {
    this.parts =  fb.group({
      'hour': '',
      'minute': ''
    });

    // control focus
    fm.monitor(elRef.nativeElement, true).subscribe(origin => {
      this.focused = !!origin;
      this.stateChanges.next();
    });

    this._onChange = (_: any) => {
    };
    if (this.ngControl) {
      this.ngControl.valueAccessor = this;
    }
  }

  // value
  @Input()
  get value(): Time | null {
    console.log('Getting value');
    const n = this.parts.value;
    if (n.hour.length === 2 && n.minute.length === 2) {
      return new Time(n.hour, n.minute);
    }
    return null;
  }

  set value(time: Time | null) {
    console.log('Setting value to: ', time);
    time = time || new Time('', '');
    this.parts.setValue({hour: time.hour, minute: time.minute});
    this.stateChanges.next();
  }

  ngOnDestroy() {
    this.stateChanges.complete();
    this.fm.stopMonitoring(this.elRef.nativeElement);
  }

  registerOnChange(fn: any): void {
    console.log('registered');
    this._onChange = fn;
  }

  registerOnTouched(fn: any): void {
  }

  setDisabledState(isDisabled: boolean): void {
  }

  writeValue(value: any): void {
    console.log('received value: ', value);
    if ((value !== this.parts.getRawValue()) && value) {
      console.log('writing value to: ', value);
      this.parts.setValue({hour: value.hour, minute: value.minute});
      console.log('new value: ', this.parts.getRawValue());
    }
  }

}

父组件中的HTML是这样的:

<mat-form-field appearance="outline">
          <mat-label>End Time</mat-label>
          <app-timepicker [required]="true"
            [(ngModel)]="endTimeObject" #endTime="ngModel" name="endTime" ngDefaultControl>
          </app-timepicker>
</mat-form-field>

【问题讨论】:

    标签: angular typescript angular2-forms angular-components controlvalueaccessor


    【解决方案1】:

    如果 setter: set value 没有被调用,这通常是因为你没有改变“value”值,你应该做类似 this.value = ".. .";

    要做到这一点并获得更多控制,我通常会在我的组件的内部输入上添加一个 [formControl]="myControl"(如果我有的话 :))并在组件中执行类似的操作:

    myControl = new FormControl();
    
    this.myControl.onStatusChange.subscribe( (newValue) => {
      this.value = newValue;
    });
    

    此外,[(ngModel)] 不会更新是正常的,因为您从未调用 this._onChange() 回调。

    registerOnChage 方法为您提供了一个回调,当您从组件内部更新值以通知 ngModel/formControl 时必须调用该回调。我想你应该添加设定值:

     set value(time: Time | null) {
        console.log('Setting value to: ', time);
        time = time || new Time('', '');
        const newValue = {hour: time.hour, minute: time.minute};
        this.parts.setValue(newValue );
        this._onChange(newValue); // call the callback :)
        this.stateChanges.next();
      }
    

    有关更多信息,您可以在此处找到 controlValueAccessor 的默认实现。您可以在使用 ngModel 的每个组件中扩展此类并简单地更改值 (this.value = 'newValue') 并覆盖 writeValue 因为它通常需要更改以满足您的组件需求。 https://github.com/xrobert35/asi-ngtools/blob/master/src/components/common/default-control-value-accessor.ts

    【讨论】:

    • 但如果是这样的话,即使没有调用 this._onChange,我也不应该看到 console.log 吗?
    • 设置值将在代码中的某处调用,您将执行“this.value = ...;”我在你的代码中看不到这个
    • 没错,如果我不清楚,对不起。控制台中没有记录“设置值”。
    • 我认为注册更改功能会检测到更改。我应该在哪里设置值?
    • 我必须修复更多的东西才能让它工作,特别是设置 ngModelChange。尽管如此,你的想法向我展示了正确的方向,所以谢谢你。
    猜你喜欢
    • 2020-08-08
    • 1970-01-01
    • 2019-07-12
    • 2016-08-06
    • 1970-01-01
    • 2018-04-12
    • 2016-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多