Search code examples
javascriptangularon-screen-keyboard

Submit form using on screen keyboard


I am trying to submit a form using an on screen keyboard but am not sure how to go about this. Essentially I need be able to see the characters that I click on in the on screen keyboard when I click the submit button on my form.

I have a directive that has the methods I use for listing the events like onFocus onBlur. I have a component that lists the different key and mouse events like keyPressed _enterPressed etc.

Here is my code and a stackblitz link below

service.ts

private _enterPressed: Subject<void>;

get enterPressed() {
  return this._enterPressed;
}

fireEnterPressed() {
  this._enterPressed.next();
}

directive

private onEnter() {
  let element = this.el.nativeElement;
  let inputEl = element.querySelector('input');
  alert("Enter"+ inputEl.value);
}

app component.ts

submit() {
  //submit forms
  alert('submit');
}

Here is a stackblitz example of the code https://stackblitz.com/edit/onscreen-keyboard-5uxhyo?file=src%2Fapp%2Fapp.component.ts

When I use the on screen keyboard to input characters into the input fields, and then I click the submit button I do not see the characters that I have entered however if I type normally on my computers keyboard and click submit then i can see the values alerted.

Any idea how I can fix this?


Solution

  • Your keyboard only change the "element.value".

    You can inject the "NgControl" in your osk-input.directive

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

    And in your functions onKey and onBackspace add this.control.control.setValue(...)

      private onKey(key: string) {
        let element = this.el.nativeElement,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);
    
        //<--add this lines--//
        if (this.control)
           this.control.control.setValue(element.value) 
        ...
      }
    
      private onBackspace() {
        let element = this.el.nativeElement,start = element.selectionStart,end = element.selectionEnd;
        ...
        this.measure.textContent = element.value.substr(0, start);
        element.value = element.value.substr(0, start) + element.value.substr(end);
    
        //<--add this lines--//
        if (this.control)
           this.control.control.setValue(element.value) 
        ...
      }
    

    BTW. Your onEnterFunction should be some like

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

    So, you can use in your .html like

    <form [formGroup]="setupForm">
      <input appOskInput formControlName="email" 
            (keydown.enter)="mobile.focus()" />
      <input #mobile appOskInput formControlName="mobile" 
            (keydown.enter)="button.focus()" />
      <button #button type="button" (click)="submit()">Submit</button>
    </form>
    

    Your forked stackblitz