使用屏幕键盘时自定义 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输入字段。有人可以帮忙吗?
问题:
您正在将指令添加到自定义元素并侦听 自定义元素而不是实际输入字段 上的事件。因为,指令中有 focus
和 blur
事件的 @HostListener
,所以在自定义组件的情况下不会触发这些事件。因为您的自定义组件不会触发 focus
和 blur
事件。 (如果我们希望任何自定义元素可聚焦,我们添加 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
我正在尝试将使用屏幕键盘键入的值输入自定义 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输入字段。有人可以帮忙吗?
问题:
您正在将指令添加到自定义元素并侦听 自定义元素而不是实际输入字段 上的事件。因为,指令中有 focus
和 blur
事件的 @HostListener
,所以在自定义组件的情况下不会触发这些事件。因为您的自定义组件不会触发 focus
和 blur
事件。 (如果我们希望任何自定义元素可聚焦,我们添加 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