開発覚書はてな版

個人的な開発関連の備忘録

【Angular】IE11用number Directive

概要

IE11では<input type="number">を指定しても数値以外の入力が可能です。
今回はDirectiveを使用して数値のみを入力する共通処理を実装したいと思います。

動作環境

  • TypeScript 2.9.x
  • Angular 6.1.x

実装方針

  • Directiveで共通化
  • @HostListener('keypress')で数値のみを入力する処理を実装
  • フォーカスが外れたら数値以外を除外(0が連続で入力される対策)

サンプルソース

custom-number.directive.ts
import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: 'input[customNumber]'
})
export class CustomNumberDirective {

  /** inputタグ */
  private inputElement: HTMLInputElement;

  /**
   * CustomNumberDirective 生成処理
   * @param elementRef
   */
  constructor(private elementRef: ElementRef) {
    if (!this.elementRef || !this.elementRef.nativeElement) return;
    this.inputElement = <HTMLInputElement>this.elementRef.nativeElement;
  }

  /**
   * 数値のみ入力
   * @param event
   */
  @HostListener('keypress', ['$event'])
  onKeyPress(event: KeyboardEvent) {
    if (!'0123456789'.includes(event.key))
      event.preventDefault();
  }

  /**
   * フォーカスが外れた時に数値整形
   */
  @HostListener('blur')
  onBlur(): void {
    if (!this.inputElement) return;
    const value = this.inputElement.value;
    if (value === null || value === '') return;

    const num = Number(value);

    if (!isNaN(num))
      this.inputElement.value = num.toString();
  }

}
app.component.ts
@Component({
  selector: 'app-root',
  template: `
    <h2>IE11 Number Directive Sample</h2>
    <div>
      <ul>
        <li>type=text:<input type="text" [(ngModel)]="text1"> - {{ text1 }}</li>
        <li>type=number:<input type="number" [(ngModel)]="num1"> - {{ num1 }}</li>
        <li>type=number+customNumber:<input type="number" customNumber [(ngModel)]="num2"> - {{ num2 }}</li>
      </ul>
    </div>
  `
})
export class AppComponent {
  text1: string;
  num1: number;
  num2: number;
}
実行結果

f:id:kakkoya:20180918211236g:plain

サンプルソース一式

github.com