angular: директивное преобразование значения управления формой - PullRequest
1 голос
/ 14 октября 2019

Я хочу преобразовать элемент управления слагом, когда пользователь вводит имя элемента управления. Я применяю такие преобразования, как изменение пробелов к дефисам (-) и т. Д.

Я создал для этого директиву, которая работает частично. Он преобразует значение для поля ввода пули, но не изменяет значение для элемента управления формы пули при вводе имени.

Вот действующий код: https://stackblitz.com/edit/angular-slug-transform

Директива:

import { Directive, HostListener } from "@angular/core";
import { NgControl } from "@angular/forms";

@Directive({
  selector: "[formControlName][appSlugTransform]"
})
export class SlugTransformDirective {
  constructor(public ngControl: NgControl) {}

  @HostListener("ngModelChange", ["$event"])
  onModelChange(event) {
    let newVal = this.transform(event);
    this.ngControl.valueAccessor.writeValue(newVal);
  }

  transform(value) {
    let text = value.toLowerCase();
    if (text.charAt(0) == " ") {
      text = text.trim();
    }
    if (text.charAt(text.length - 1) == "-") {
      //text = (text.replace(/-/g, ""));
    }
    text = text.replace(/ +/g, "-");
    text = text.replace(/--/g, "-");
    text = text.normalize("NFKD").replace(/[\u0300-\u036f]/g, ""); // Note: Normalize('NFKD') used to normalize special alphabets like óã to oa
    text = text.replace(/[^a-zA-Z0-9 -]/g, "");

    return text;
  }
}

В примере вы можете увидеть:

  • Если вы введете в поле ввода name, слаг преобразуется в его поле ввода, но его управляющее значение формы не преобразуется.
  • Когда вы вводите в поле ввода slug, оно работает правильно, т.е. преобразуются как поле, так и значение управления.

Ответы [ 3 ]

0 голосов
/ 14 октября 2019

Проблема в том, что this.ngControl.valueAccessor.writeValue(newVal) не запускает обновление модели. Не совсем уверен, почему это так, но вот альтернативный подход, который вы можете использовать с ElementRef & dispatchEvent для запуска обновления модели:

Сначала обновите значение ввода, используя ElementRef, а затем используйте dispatchEvent.

this.el.value = newVal;
this.el.dispatchEvent(new Event('input'))

демо: https://stackblitz.com/edit/angular-slug-transform-sdmeto



Полностью обновленная директива:

import { Directive, HostListener, ElementRef, OnInit } from "@angular/core";
import { NgControl } from "@angular/forms";

@Directive({
  selector: "[formControlName][appSlugTransform]"
})
export class SlugTransformDirective implements OnInit {
  private el: any;

  constructor(public ngControl: NgControl, private elementRef: ElementRef) {
    this.el = this.elementRef.nativeElement;
  }

  ngOnInit() {
    this.el.value = this.transform(this.el.value);
  }

  @HostListener("ngModelChange", [ "$event"])
  onNgModelChange(event) {
    let newVal = this.transform(event);
    // this.ngControl.valueAccessor.writeValue(newVal);
    this.el.value = newVal;
    this.el.dispatchEvent(new Event('input'))
  }

  transform(value) {
    let text = value.toLowerCase();
    if (text.charAt(0) == " ") {
      text = text.trim();
    }
    if (text.charAt(text.length - 1) == "-") {
      //text = (text.replace(/-/g, ""));
    }
    text = text.replace(/ +/g, "-");
    text = text.replace(/--/g, "-");
    text = text.normalize("NFKD").replace(/[\u0300-\u036f]/g, ""); // Note: Normalize('NFKD') used to normalize special alphabets like óã to oa
    text = text.replace(/[^a-zA-Z0-9 -]/g, "");

    return text;
  }
}

Другой подход, которыйВы можете попробовать использовать patchValue вместо writeValue, например:

this.ngControl.control.patchValue(newVal);

Это должно вызвать изменение модели. (не проверено)

0 голосов
/ 16 октября 2019

Наконец-то решена проблема, и волшебство идет сюда

ngOnInit(): void {
  this.valueSubscription = this.ngControl.control.valueChanges.subscribe(
    value => {
      const newVal = this.transform(value);
      this.ngControl.control.setValue(newVal, { emitEvent: false });
    }
  );
}

Я использую valueChanges вместо HostListener для прослушивания изменения значения.

И для обновления значения я сейчас используюsetValue метод управления.

Вот бегущий код: https://stackblitz.com/edit/angular-slug-directive

0 голосов
/ 14 октября 2019
  1. Добавьте директиву к имени FormControl,
  2. Получите контейнер управления в директиве
  3. Получите элемент управления Slug и patchValue к нему.
  4. Удалите("name").onValueChanges(), поскольку директива справится с этим.

https://stackblitz.com/edit/angular-slug-transform-zbkdwv

...