kendo-dateinput and tab-like directives

0 Answers 20 Views
DateInput
Ron
Top achievements
Rank 1
Iron
Iron
Ron asked on 15 Mar 2024, 07:52 PM
I had a customer who would like us to make 'Enter' work similar to Tab for moving across consecutive fields. For that I built a directive to tag onto various open fields where it was applicable (ie. inputs, textareas, kendo-dropdownlist, kendo-dateinput, just avoiding multicolumncombobox because that requires Enter as part of it's functioning).

What I've noticed is this will work for inputs, textareas, even kendo-dropdownlists, but it seems like for kendo-dateinput it will never 'tab' onto or out of those. Here's an example of both the directive and the fields I'm talking about living in the wild:

import { Directive, HostListener, ElementRef } from '@angular/core';

@Directive({
  selector: '[tab13]'
})
export class Tab13Directive {

  constructor(private el: ElementRef) { }

  @HostListener('keydown', ['$event'])
  onKeyDown(event: KeyboardEvent) {
    if (event.key === 'Enter') {
      event.preventDefault();
      const nextElement = this.findNextFocusableElement();
      if (nextElement) {
        nextElement.focus();
      }
    }
  }

  private findNextFocusableElement(): HTMLElement | null {
    const tab13Elements = document.querySelectorAll('[tab13]');
    const currentIndex = Array.from(tab13Elements).indexOf(this.el.nativeElement);

    for (let i = currentIndex + 1; i < tab13Elements.length; i++) {
      if (this.isFocusable(tab13Elements[i] as HTMLElement)) {
        return tab13Elements[i] as HTMLElement;
      }
    }

    return null;
  }

  private isFocusable(element: HTMLElement): boolean {
    return (
      element.hasAttribute('tab13')
    );
  }
}

HTML example:

<div style="width: 100%; display: flex; flex-wrap: wrap; white-space: nowrap;">
  <input tab13 id="{{ '0-qs-code' }}" tabindex="{{'120007'}}" />
  <input tab13 id="{{ '0-qs-email' }}" tabindex="{{'120008'}}" />
  <kendo-dateinput tab13 id="{{ '0-qs-rfqsent' }}" tabindex="{{'120009'}}" format="M/d/yy" placeholder="M/d/yy"></kendo-dateinput>
  <kendo-dateinput tab13 id="{{ '0-qs-rfqrec' }}" tabindex="{{'120010'}}" format="M/d/yy" placeholder="M/d/yy"></kendo-dateinput>
  <input tab13 id="{{ '0-qs-quoteno' }}" tabindex="{{'120011'}}"  />
</div>

The tab works across all of these but for reasons I'm unfamiliar with the tab13 selector fails at 0-qs-email when the next input is a kendo-dateinput and it fails in 0-qs-rfqsent but it will work from 0-qs-rfqrec because the next selector is an input rather than a kendo-dateinput.

I'm hoping to up my product knowledge a bit and get a better grasp of what the kendo-dateinput is doing under the hood that might explain this behavior and what workarounds might be available for improving the directive.

Yanmario
Telerik team
commented on 20 Mar 2024, 10:01 AM

Hi Ron,

It seems that the directive is trying to focus on the kendo-dateinput element rather than the input that is inside the component. What I would suggest is to modify your directive to also take into account the inner input element of the DateInputs. 

The following example demonstrates how to focus the inner input of the DateInput:

https://stackblitz.com/edit/angular-tdyp6i?file=src%2Fapp%2Ftest.directive.ts,src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.module.ts

I hope this helps.

Regards,
Yanmario
Progress Telerik

Ron
Top achievements
Rank 1
Iron
Iron
commented on 20 Mar 2024, 01:41 PM

Yanmario,

Thank you for your response on this.

I did just try making the updates suggested to my directive:

  @HostListener('keydown', ['$event'])
  onKeyDown(event: KeyboardEvent) {
    if (event.key === 'Enter') {
      event.preventDefault();
      const nextElement = this.findNextFocusableElement();
      let dateInput: any = document.querySelector('.k-input-inner');
      dateInput.focus();
      if (nextElement) {
        nextElement.focus();
      }
    }
  }

The behavior seems roughly the same (can't 'Enter' into a date input from the input to the left or above it but I can exit if the next tab13 is a normal input) and perhaps the only difference is that in your demo I can Enter into the first date input but not the second. I'd need to know a bit more about what states for the kendo date inputs are impassible due to needing the Enter key for other purposes or what other more mutable structure might be in the way.
Yanmario
Telerik team
commented on 25 Mar 2024, 08:25 AM

Hi Ron,

Generally, the whole directive itself needs to be modified so that it takes into account the DateInputs and their inner input element. The following example shows how you can focus from one DateInput to another, and from there you can modify the directive.

https://stackblitz.com/edit/angular-tdyp6i-eajdtv?file=src%2Fapp%2Ftest.directive.ts,src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.module.ts

I hope this helps.

Regards,
Yanmario
Progress Telerik

No answers yet. Maybe you can help?

Tags
DateInput
Asked by
Ron
Top achievements
Rank 1
Iron
Iron
Share this question
or