Estoy tratando de obtener valores que escribo usando un teclado en pantalla en un campo de entrada de elemento HTML personalizado para mostrar.
Sin embargo, actualmente obtengo cadenas vacías. Si uso un campo de entrada normal, entonces funciona bien.
Aquí hay un fragmento de mi código y un ejemplo de stackblitz que tendrá un código detallado.
HTML
<form-input appOskInput [formStatus]="formStatus" [parentFormGroup]="setupForm" [data]="{ formControlName: 'email', name: 'email' }"> </form-input> <app-keyboard></app-keyboard>directiva de teclado
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(); }Aquí está el stackblitz https://stackblitz.com/edit/onscreen-keyboard-hlmkvv?file=src/app/app.component.ts
Verá que los valores se muestran cuando se ingresan desde un campo de entrada normal, pero no puedo hacer que suceda lo mismo cuando uso mi campo de entrada de elemento HTML personalizado. He comentado el campo de entrada HTML personalizado en el código de la página HTML. ¿Alguien puede ayudar por favor?
Tema:
Está agregando la directiva a un elemento personalizado y escuchando los eventos en el elemento personalizado en lugar del campo de entrada real . Dado que tiene @HostListener para eventos de focus y blur dentro de la directiva, estos eventos no se activan en el caso de un componente personalizado. Porque su componente personalizado no dispara eventos de focus y blur . (Si queremos que cualquier elemento personalizado sea enfocable, agregamos tabindex=0 para que sea enfocable en el orden de tabulación natural de la página web).
¿Por qué funciona en elementos de entrada nativos?
Porque los elementos de entrada nativos emiten eventos de focus y blur . Por lo tanto, puede ver el teclado virtual cuando aplica la directiva a la input nativa.
Solución:
Debe agregar detectores de eventos al campo de input nativo dentro de su componente personalizado. Dado que la directiva es genérica, puede usar querySelector() en nativeElement dentro de OskInputDirective para acceder al campo de entrada en particular.
En OskInputDirective , agregue focus y blur de oyentes en ngAfterViewInit :
ngAfterViewInit(){ this.inputEl=this.el.nativeElement.querySelector('input'); this.inputEl?.addEventListener('focus',this.onFocus.bind(this)); this.inputEl?.addEventListener('blur',this.onBlur.bind(this)); } Ahora, puedes usar this.inputEl para referirte al elemento de entrada dentro de tu método onKey() .
Nota 1: aquí, vinculamos las devoluciones de llamada con el contexto de OskInputDirective . De lo contrario, this se referirá al evento DOM.
Nota 2: dado que nos estamos suscribiendo manualmente al evento DOM, Angular no podrá detectar cambios ni actualizar su valor FormControl . Debe emitir un evento cuando cambia el valor de input desde el teclado virtual.
En onKey() , llame al emisor de eventos al final. Ahora, escuche este evento en el padre y actualice el valor de control de formulario correspondiente:
this.inputChanged.emit(element.value); this.updateScrollPosition();Aquí está el stackblitz bifurcado con un elemento de entrada personalizado creado como referencia. https://stackblitz.com/edit/onscreen-keyboard-na5kqr?file=src/app/app.component.ts