Angular | Автоматически фокусировать следующий вход на максимальной длине - PullRequest
0 голосов
/ 12 апреля 2020

Я пытаюсь придумать лучший способ сфокусировать следующий вход на Angular без необходимости вручную вводить то, что я хочу сфокусировать.

Это мой html, который В настоящее время у меня есть ...

<div class="mb-2 digit-insert d-flex align-items-center">
  <div class="confirmation-group d-flex">
    <div class="digit-wrapper">
      <input #digitOne type="text" (paste)="onDigitPaste($event)" maxlength="1"
        (keyup)="onDigitInput($event, null, digitTwo)" />
    </div>
    <div class="digit-wrapper">
      <input #digitTwo type="text" maxlength="1" (keyup)="onDigitInput($event, digitOne, digitThree)" />
    </div>
    <div class="digit-wrapper">
      <input #digitThree type="text" maxlength="1" (keyup)="onDigitInput($event, digitTwo, digitFour)" />
    </div>
  </div>
  <span class="confirmation-divider m-3">-</span>
  <div class="confirmation-group d-flex">
    <div class="digit-wrapper">
      <input #digitFour type="text" maxlength="1" (keyup)="onDigitInput($event, digitThree, digitFive)" />
    </div>
    <div class="digit-wrapper">
      <input #digitFive type="text" maxlength="1" (keyup)="onDigitInput($event, digitFour, digitSix)" />
    </div>
    <div class="digit-wrapper">
      <input #digitSix type="text" maxlength="1" (keyup)="onDigitInput($event, digitFive, null)" />
    </div>
  </div>
</div>

Как вы можете видеть, у меня есть событие key up, которое я передаю, на котором хочу сфокусироваться, введен ли ввод.

Это машинопись разметка ...

onDigitInput(event: any, previousElement: any, nextElement: any): void {
    if (event.code !== 'Backspace' && nextElement !== null) {
        nextElement.focus();
    }

    if (event.code === 'Backspace' && previousElement !== null) {
        previousElement.focus();
        previousElement.value = '';
    }
}

Мне было интересно, есть ли способ сделать это с помощью директивы или просто что-то более приятное, чем это сейчас?

Ответы [ 2 ]

0 голосов
/ 12 апреля 2020

Здесь я использовал хост-слушатель для захвата событий клавиатуры и пользовательскую директиву для обработки фокуса.

  1. focus.directive.ts

Это имеет Входная переменная, которая является типом EventEmitter, который принимает строковый параметр. Этот параметр будет содержать идентификатор элемента для фокусировки.

import { Directive, EventEmitter, Input, OnInit, Renderer2 } from '@angular/core';

@Directive({
 selector: '[appFocus]'
})
export class FocusDirective implements OnInit {
@Input('appFocus') eventEmitter: EventEmitter<string>;

  constructor(private renderer: Renderer2) { }

  ngOnInit() {
   this.eventEmitter.subscribe(elementId => {
    try {
     this.renderer.selectRootElement(elementId).focus();
    } catch (ex) {
     // If the element doesn't exist or if the element disappears when this called then no need to do anything
    }
   });
  }
}

input.component.ts

import { Component, HostListener, EventEmitter } from '@angular/core';

@Component({
 selector: 'app-inputs',
 templateUrl: './inputs.component.html'
})

export class InputsComponent {
  inputFocusEmitter = new EventEmitter<string>();

  @HostListener('window:keydown', ['$event'])
  HandlKeyEvents(event) {
   const key = event.key.toLocaleLowerCase();
   const inputIds = ['digitOne', 'digitTwo', 'digitThree'];
   let elementId = '';

   switch (key) {
    case 'backspace':
     elementId = event.target.id;
     const prevInputIndex = inputIds.indexOf(elementId) - 1;
     if (prevInputIndex >= 0) {
      this.inputFocusEmitter.emit(`#${inputIds[prevInputIndex]}`);
     }
     break;

   default:
    elementId = event.target.id;
    const index = inputIds.indexOf(elementId);
    const nextInputIndex = index + 1;
    if (nextInputIndex > 0 && nextInputIndex < inputIds.length) {
     this.inputFocusEmitter.emit(`#${inputIds[nextInputIndex]}`);
    }
    break;
  }
}

input.component. html

Здесь указывается фокус связаны с каждым входным элементом

 <div class="mb-2 digit-insert d-flex align-items-center">
      <div class="confirmation-group d-flex">
          <div class="digit-wrapper">
              <input #digitOne type="text" maxlength="1"  [appFocus]="inputFocusEmitter"/>
          </div>
          <div class="digit-wrapper">
              <input #digitTwo type="text" maxlength="1"  [appFocus]="inputFocusEmitter"/>
          </div>
          <div class="digit-wrapper">
              <input #digitThree type="text" maxlength="1" [appFocus]="inputFocusEmitter"/>
          </div>
      </div>
 </div> 

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

0 голосов
/ 12 апреля 2020

Измените свой элемент input на это:

<input #digitSix type="text" maxlength="1" (keyup)="onDigitInput($event)" />

, а затем измените реализацию вашей функции на это:

onDigitInput(event){

   let element;
   if (event.code !== 'Backspace')
        element = event.srcElement.nextElementSibling;

    if (event.code === 'Backspace')
        element = event.srcElement.previousElementSibling;

    if(element == null)
        return;
    else
        element.focus();
}

В результате получится намного более чистый код.

Работает с этим кодом:

<div class="mb-2 digit-insert d-flex align-items-center">
  <div class="confirmation-group d-flex">
      <input #digitOne type="text" (paste)="onDigitPaste($event)" maxlength="1"
        (keyup)="onDigitInput($event)" />
      <input #digitTwo type="text" maxlength="1" (keyup)="onDigitInput($event)" />
      <input #digitThree type="text" maxlength="1" (keyup)="onDigitInput($event)" />
  </div>
  <span class="confirmation-divider m-3">-</span>
  <div class="confirmation-group d-flex">
      <input #digitFour type="text" maxlength="1" (keyup)="onDigitInput($event)" />
      <input #digitFive type="text" maxlength="1" (keyup)="onDigitInput($event)" />
      <input #digitSix type="text" maxlength="1" (keyup)="onDigitInput($event)" />
  </div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...