【问题标题】:Change FormControl value from ControlValueAccessor从 ControlValueAccessor 更改 FormControl 值
【发布时间】:2021-01-25 11:43:22
【问题描述】:

我正在尝试仅为案例创建一个指令。我创建了以下代码,但尝试制作 formGroup.value 时遇到问题。 该指令在视觉上更改了值(通过使用_Renderer2),但formControl仍然具有原始值,并且当使用formGroup.value从表单中获取数据时,值是小写的。有可能解决这个问题吗?谢谢

<form [formGroup]="formGroup">
    <mat-form-field>
        <input placeholder="Street" formControlName="streetName" matInput uppercase>
    </mat-form-field>
</form>

import { Directive, ElementRef, Optional, Renderer2, Self } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';

@Directive({
  selector: "textarea[uppercase], input[uppercase]",
  host: {
    '(input)': 'writeValue($event.target.value)',
    '(blur)': 'onTouched()',
  }
})
export class UppercaseDirective implements ControlValueAccessor {

  onChange = (_: any) => {
    console.log("onChange", _)
  };

  onTouched = () => {
    console.log("onTouched")
  };

  constructor(private _renderer: Renderer2, private _elementRef: ElementRef, @Optional() @Self() public ngControl: NgControl) {
    ngControl.valueAccessor = this;
  }

  writeValue(value: any): void {
    this._renderer.setProperty(this._elementRef.nativeElement, 'value', this.transformValue(value));
  }

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

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

  setDisabledState(isDisabled: boolean): void {
    this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
  }

  private transformValue(value: string): string {
    return typeof value === 'string'
      ? value?.toUpperCase()
      : value;
  }
}

【问题讨论】:

  • 这是有道理的,您更改 DOM 的角度如此之大,无法识别这一点。我不知道如何帮助你,因为我上次使用 Angular 已经 9 个月了,但我认为你需要尝试获得“表单控件”本身
  • 指令只改变我们在 DOM 中看到的内容,它们实际上并没有改变值本身。

标签: angular typescript controlvalueaccessor


【解决方案1】:

您正在混合自定义表单控件和指令的概念。我不知道是否有另一种方法,但是,如果你想制作一个转换一个输入的指令,你可以让它创建一个 HTMLEvent。有些人喜欢

@Directive({
  selector: "[toUpperCase]"
})
export class ToUpperCaseDirective implements AfterViewInit {
  constructor(private elementRef: ElementRef) {}

  @HostListener("input", ["$event"]) onKeyDown(event: KeyboardEvent) {
    this.setUpper();
  }
  ngAfterViewInit() {
    setTimeout(() => {
      this.setUpper();
    });
  }
  setUpper() {
    const target = this.elementRef.nativeElement;
    let pos = target.selectionStart; //get the position of the cursor
    target.value = target.value.toUpperCase();
    var evt = document.createEvent("HTMLEvents");
    evt.initEvent("input", false, true);
    this.elementRef.nativeElement.dispatchEvent(evt);
    target.selectionStart = target.selectionEnd = pos; //return the position
  }
}

注意:我真的不认为该指令是解决大写输入问题的好方法。对我来说最好简单地使用 css

<input style="text-transform:uppercase">

然后,当我们要检查值转换时,使用 toUpperCase。

【讨论】:

  • 感谢您的回复。用 CSS 做对我来说没用,因为它只是视觉上的变化,当我从 formgroup.value 获取数据时,它是小写的。我会测试你的指令
猜你喜欢
  • 1970-01-01
  • 2021-12-10
  • 2018-01-27
  • 2020-09-15
  • 2021-06-02
  • 2017-03-23
  • 2019-01-30
  • 2017-09-16
  • 2021-11-11
相关资源
最近更新 更多