You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过TS的isKeyboardActive方法为输入框动态添加appOskInput指令?

需求与问题

我想要实现:当调用TS文件中的isKeyboardActive方法让输入框获取焦点时,为该输入框添加名为appOskInput的指令。以下是我的相关代码:

HTML代码

<form-input
    (inputChanged)="onInputChanged($event,'accountNumber')"
    (blurChanged)="onBlurChanged($event)"
    [formStatus]="formStatus"
    [parentFormGroup]="setupForm"
    [data]="{
      formControlName: 'accountNumber',
      name: 'accountNumber',
      label: Accounnt Number
    }">
</form-input>

<a (click)="isKeyboardActive()" class="use-kepypad"><img class="mouse-icon" src="assets/images/ford/mouse-computer.png"> <img class="mouse-icon" src="assets/images/ford/mouse-computer-hover.png">{{ 'preLogon.common.label.useKeypad'|translate }}</a>

TS代码

@ViewChild(FormInputComponent, { read: ElementRef }) formInput: ElementRef;

isKeyboardActive() {
  const input = this.formInput.nativeElement.querySelector('input');
  input.focus();
}

指令代码

import {
  Directive,
  OnInit,
  ElementRef,
  HostListener,
  Optional,
  EventEmitter,
  Output,
} from '@angular/core';
import { NgControl } from '@angular/forms';
import { KeyboardService } from './keyboard.service';
import { Subscription } from 'rxjs';

@Directive({
  selector: '[appOskInput]',
})
export class OskInputDirective implements OnInit {
  private keySubscription: Subscription;
  private backspaceSubscription: Subscription;
  private enterSubscription: Subscription;
  private measure: HTMLElement;
  private inputEl: HTMLInputElement;
  private isBlurTrue: boolean = false;
  @Output() inputChanged = new EventEmitter();
  @Output() blurChanged = new EventEmitter();

  constructor(
    @Optional() private control: NgControl,
    private el: ElementRef,
    private keyboard: KeyboardService,
  ) {}

  ngOnInit() {
    let thisStyle = window.getComputedStyle(this.el.nativeElement);
    this.measure = document.createElement('span');
    this.measure.style.position = 'absolute';
    this.measure.style.right = '100%';
    this.measure.style.font = thisStyle.font;
    document.body.appendChild(this.measure);
  }

  ngAfterViewInit() {
    if (this.el.nativeElement instanceof HTMLInputElement) {
      this.inputEl = this.el.nativeElement;
      return;
    }
    this.inputEl = this.el.nativeElement.querySelector('input');
  }

  @HostListener('focus')
  private onFocus() {
    this.isBlurTrue = false;
    this.blurChanged.emit(this.isBlurTrue);
    this.keyboard.fireKeyboardRequested(true);
    this.subscribeToKeyboardEvents();
  }

  @HostListener("onBlur")
  private onBlur() {
    this.isBlurTrue = true;
    this.blurChanged.emit(this.isBlurTrue);
    this.keyboard.fireKeyboardRequested(false);
    this.unsubscribeFromKeyboardEvents();
  }

  private subscribeToKeyboardEvents() {
    this.keySubscription = this.keyboard.keyPressed.subscribe((key) =>
      this.onKey(key)
    );
    this.backspaceSubscription = this.keyboard.backspacePressed.subscribe((_) =>
      this.onBackspace()
    );
    this.enterSubscription = this.keyboard.enterPressed.subscribe((_) =>
      this.onEnter()
    );
  }

  private unsubscribeFromKeyboardEvents() {
    this.keySubscription.unsubscribe();
    this.backspaceSubscription.unsubscribe();
    this.enterSubscription.unsubscribe();
  }

  private onKey(key: string) {
    let element = this.inputEl,
      start = element.selectionStart,
      end = element.selectionEnd;
    this.measure.textContent = element.value.substr(0, start) + key;
    element.value = element.value.substr(0, start) + key + element.value.substr(end);
    if (this.control) this.control.control.setValue(element.value);
    element.focus();
    element.selectionStart = element.selectionEnd = start + 1;
    this.inputChanged.emit(element.value);
    this.updateScrollPosition();
  }

  private onBackspace() {
    let element = this.inputEl,
      start = element.selectionStart,
      end = element.selectionEnd;

    if (start == 0) {
      return;
    }

    if (start == end) {
      start--;
    }

    this.measure.textContent = element.value.substr(0, start);
    element.value = element.value.substr(0, start) + element.value.substr(end);
    if (this.control) this.control.control.setValue(element.value);
    element.focus();
    element.selectionStart = element.selectionEnd = start;
    this.inputChanged.emit(element.value);
    this.updateScrollPosition();
  }

  private updateScrollPosition() {
    let element = this.el.nativeElement;
    element.scrollLeft = this.measure.offsetWidth - (element.clientWidth - 10);
  }

  private onEnter() {
    const ev = new KeyboardEvent('keydown', {
      code: 'Enter',
      key: 'Enter'
    });
    this.el.nativeElement.dispatchEvent(ev);
  }
}

内容的提问来源于stack exchange,提问作者RRB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 13:27:21