使用屏幕键盘时自定义 HTML 元素输入字段的表单值不显示

Form values from custom HTML element input field not displaying when using on-screen keyboard

我正在尝试将使用屏幕键盘键入的值输入自定义 HTML 元素输入字段以显示。

但是我目前得到的是空字符串。如果我使用普通输入字段,那么它工作正常。

这是我的代码片段和一个包含详细代码的 stackblitz 示例。

HTML

<form-input
    appOskInput
    [formStatus]="formStatus"
    [parentFormGroup]="setupForm"
    [data]="{
             formControlName: 'email',
             name: 'email'
            }">
</form-input>

<app-keyboard></app-keyboard> 

键盘指令

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

这里是 stackblitz https://stackblitz.com/edit/onscreen-keyboard-hlmkvv?file=src/app/app.component.ts

您会看到从普通输入字段输入时会显示值,但在使用我的自定义 HTML 元素输入字段时无法得到相同的结果。我已经在HTML页面的代码中注释掉了自定义HTML输入字段。有人可以帮忙吗?

问题:

您正在将指令添加到自定义元素并侦听 自定义元素而不是实际输入字段 上的事件。因为,指令中有 focusblur 事件的 @HostListener,所以在自定义组件的情况下不会触发这些事件。因为您的自定义组件不会触发 focusblur 事件。 (如果我们希望任何自定义元素可聚焦,我们添加 tabindex=0 以使其在网页的自然 Tab 键顺序中可聚焦)。

为什么它适用于原生输入元素?

因为本机输入元素会发出 focus & blur 事件。因此,当您将指令应用于本机 input.

时,您可以看到虚拟键盘

解法:

您需要将事件侦听器添加到自定义组件内的本机 input 字段。由于该指令是通用的,您可以在 OskInputDirective 内的 nativeElement 上使用 querySelector() 来访问特定的输入字段。

OskInputDirective 中,在 ngAfterViewInit 中添加 focus & blur 听众:

 ngAfterViewInit(){
    this.inputEl=this.el.nativeElement.querySelector('input');
    this.inputEl?.addEventListener('focus',this.onFocus.bind(this));
    this.inputEl?.addEventListener('blur',this.onBlur.bind(this));
  }

现在,您可以使用 this.inputEl 来引用 onKey() 方法中的输入元素。

注意 1: 这里,我们将回调与 OskInputDirective 的上下文绑定。否则,this 将引用 DOM 事件。

注意 2: 由于我们手动订阅 DOM 事件,Angular 将无法检测到更改并更新您的 FormControl 值。当您从虚拟键盘更改 input 值时,您需要发出一个事件。

onKey()中,最后调用事件发射器。现在,在父级中监听此事件并更新相应的表单控件值:

this.inputChanged.emit(element.value);
    this.updateScrollPosition();

这是带有自定义输入元素的分支 stackblitz,供参考。 https://stackblitz.com/edit/onscreen-keyboard-na5kqr?file=src/app/app.component.ts