angular auto tab directive

Angular Auto Tab Directive



Keys Points:

  1. Created an Angular custom directive
  2. Move Focus to next input field
  3. If there is a condition true on first input field, focus should auto move to next field
  4. In this example – we have input fields like Employee Id and Employee Name. So Once User enters 4 digits in Employee Id field, cursor should move to next input field Employee name.


Directive:

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

@Directive({
  selector: '[libAutoTab]'
})
export class AutoTabDirective {
  @Input() libAutoTab;
  constructor() {}
  @HostListener('input', ['$event.target']) onInput(input) {
    const length = input.value.length;
    const maxLength = input.attributes.maxlength.value;

    if (length >= maxLength && this.libAutoTab) {
      const field = document.getElementById(this.libAutoTab);
      if (field) {
        field.focus();
      }
    }
  }
}



HTML :


Input field Employee Id and Employee Name is created inside a for loop based on received data in empList array. We also given dynamic Id to field based on index value.

<div>
  <ng-container *ngFor="let emp of empList; let i = index">
    <div class="form-group">
      <label>Employee ID</label>
      <input
        type="text"
        [libAutoTab]="'empName' + i"
        [(ngModel)]="emp.empId"
        maxlength="4"
        name="empId"
        class="form-control"
        required
      />
    </div>
    <div class="form-group">
      <label>Employee Name</label>
      <input
        [id]="'empName' + i"
        type="text"
        [(ngModel)]="emp.empName"
        name="empName"
        class="form-control"
        required
      />
    </div>
  </ng-container>
</div>



Test Cases:

import { Component, DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AutoTabDirective } from './auto-tab.directive';

@Component({
  template: `
    <input
      libAutoTab="{{ tabName }}"
      value="test value"
      maxlength="6"
      id="testTab"
    />
  `
})
class TestComponent {
  tabName = 'testTab';
}
describe('AutoTabDirective', () => {
  let fixture: ComponentFixture<TestComponent>;
  let inputEl: DebugElement;
  const directive = new AutoTabDirective();

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [TestComponent, AutoTabDirective]
    });
    fixture = TestBed.createComponent(TestComponent);
    inputEl = fixture.debugElement.query(By.directive(AutoTabDirective));
  }));

  it('should create an instance', () => {
    expect(directive).toBeTruthy();
  });

  it('should focus on element if length is greater than max length', () => {
    const eventObj = {
      target: {
        value: inputEl.attributes.value,
        attributes: { maxlength: { value: inputEl.attributes.maxlength } }
      }
    };
    fixture.detectChanges();
    inputEl.triggerEventHandler('input', eventObj);
    const field = document.getElementById('testTab');
    expect(document.activeElement).toBe(field);
  });

  it('should not focus on element if length is less than max length', () => {
    const eventObj = {
      target: {
        value: 'test',
        attributes: { maxlength: { value: inputEl.attributes.maxlength } }
      }
    };
    fixture.detectChanges();
    inputEl.triggerEventHandler('input', eventObj);
    const field = document.getElementById('testTab');
    expect(document.activeElement).not.toBe(field);
  });
});



Running Demo

https://stackblitz.com/edit/angular-auto-tab-directive?embed=1&file=src/app/auto-tab.directive.ts

Lets see Useful VS Code extensions:
https://www.jsmount.com/vs-code-useful-extensions-for-web-development/

Lets run latest in Typescript :
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html

Leave a Reply

Your email address will not be published.