Angular 6 event.stopPropagation () не работает в директиве (управляемая шаблоном форма уже принимает event.data) - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь заставить компонент CitizenNumber использовать в формах.Он реализует ControlValueAccessor для ngModel.

export class CitizenNumberComponent implements ControlValueAccessor {
    private _value: string;
    @Input() placeholder = '';
    @Input() required = true;

    get value(): string {
        return this._value;
    }

    set value(value: string) {
        this._value = value;
        this.propagateChange(value);
    }

    // registers 'fn' that will be fired when changes are made
    // this is how we emit the changes back to the form
    registerOnChange(fn: any): void {
        this.propagateChange = fn;
    }

    // not used, used for touch input
    registerOnTouched(fn: any): void { }

    // this is the initial value set to the component
    writeValue(value: string): void {
        if (value) {
        this._value = value;
        }
    }

    // the method set in registerOnChange to emit changes back to the form
    propagateChange = (_: any) => { };
    }

Я делаю NumberDirective для ограничения ввода, кроме 0-9 цифр.

В numberDirective я использовал событие 'input', потому что нажатие клавиш, нажатие клавиш и keyup не работают на Android Chrome.

@Directive({
    selector: 'input[jhiNumbersOnly]'
})
export class NumberDirective {
    private specialKeys: Array<string> = ['Backspace', 'Delete', 'Insert', 'Tab', 'End', 'Home', 'ArrowRight', 'ArrowLeft'];

    @HostListener('input', ['$event']) onInput(event) {
        const key = event['data'];
        // Allow Backspace, tab, end, and home keys
        if (this.specialKeys.indexOf(key) !== -1) {
            return;
        }
        const initalValue = event.target['value'];
        event.target['value'] = initalValue.replace(/[^0-9]*/g, '');
        if (initalValue !== event.target['value']) {
            event.stopPropagation();
        }
    }
}

Наконец, все работает, но, несмотря на то, что событие остановилось, модель принимаетзначение.

Например, моя максимальная длина ввода равна 11. После ввода 10 номера, если будет введена какая-либо форма ввода ключа (кроме 0-9).

Посмотрите компонентв stackblitz ;

Можете ли вы помочь мне с моей проблемой?

1 Ответ

0 голосов
/ 24 января 2019

Вам следует заменить обработчик input на обработчик keydown. Тогда, если ключ хороший, ничего не делайте, иначе предотвратите событие.

Проблема в том, что если вы прослушиваете входное событие, будет слишком поздно, ngModel будет обновлено, поэтому вы должны прослушать событие keydown и отфильтровать его соответствующим образом.

@HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) {
  if (this.specialKeys.indexOf(e.key) !== -1 || new RegExp(/[0-9]/g).test(e.key)) {
      return;
  }
  e.preventDefault();
}

Я протестировал этот код в вашей демонстрации стекаблиц, и он работает.

РЕДАКТИРОВАТЬ : Вы упоминали, что не можете использовать обработчик нажатия клавиш, извините.

Мне удалось заставить его работать с обработчиком oninput элемента <input>, и я удалил вашу директиву на входе:

<div class = "form-group">
  <label class = "form-control-label label-color" for = "citizenNumber">Citizen Number
  </label>
  <input type = "text" 
          class = "form-control input-css" 
          name = "citizenNumber"
          id = "citizenNumber"
          #citizenNumber="ngModel"
          oninput="this.value = this.value.replace(/[^0-9]/g, '');"
          [(ngModel)] = "value"
          [placeholder] = "placeholder"
          minlength = "11"
          maxlength = "11"
          [required] = "required">
  <div *ngIf = "citizenNumber.invalid && (citizenNumber.dirty || citizenNumber.touched)"
      class = "form-text text-danger">
      <small *ngIf = "citizenNumber.errors.required">This field is required.</small>
      <small *ngIf = "citizenNumber.errors.minlength">This field must be 11 characters.</small>
      <small *ngIf = "citizenNumber.errors.invalidTc">This is not a citizen number</small>
  </div>
</div>

Вот обновленный Stackblitz .

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...