【Angular】自作したディレクティブに引数を渡そう!

ANGULAR

みなさんこんにちは、現役エンジニアのサメハックです

未経験からWebエンジニアに転職し、
正社員として5年働いたのちフリーランスとして独立しました。

Angularの解説シリーズです。

今回はディレクティブに引数を渡す方法について学んでいきましょう!

駆け出しエンジニアや未経験の方、
また新入社員を指導する先輩社員にとっても
わかりやすいように解説していきます!

この記事を読むと・・・
  • オリジナルのディレクティブが作成できる
  • ディレクティブに引数を渡すことができる

※PCにnpm、nodeがインストールされている前提で記述します。
 yarn等をお使いの方は読み替えてください。

環境がない人はcodesansbox等を使ってね!

作りたいもの

【Angular】連打防止ディレクティブを作ろう!【使いまわし可能!】
こちらの連打防止ディレクティブに引数を渡す機能を追加するよ!

実行環境

Angularのバージョンが古いと動かないことがあるよ!
うまく動かなければアップデートしてね!

連打防止ディレクティブに引数を渡そう!

連打防止するために必要となる処理は以下の3つです。

  • クリックイベントを受け取る
  • 要素にdisabled属性をtrueとし、操作不可能とする
  • 一定時間経過後、disabled属性をfalseに戻し操作可能とする
今回はこの操作不可能とする時間を引数として受け取れるようにするよ!

ディレクティブとは

ディレクティブとは、HTML要素に属性として記述する事でDOMの操作を可能とするクラスです。

連打防止のように汎用性の高いディレクティブを作成して使い回すことで
同じ処理を複数のファイルで記述する必要がなくなるので、
コードがスッキリして処理も統一されます。

使いまわしできるのが最大のメリットだよ!

初期設定

ng new my-app
cd my-app
ng generate directive directive/preventDoubleClick
ng serve -o
ng generate directive directive/prevent-double-click
これで、directiveが作成できるよ!

prevent-double-click.directive.ts

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

@Directive({
  selector: '[appPreventDoubleClick]',
})
export class PreventDoubleClickDirective {
  /**コンポーネントから引数を受け取る */
  @Input() timer!: number;

  /**disabledを解除するまでの時間※ミリ秒 */
  TIMER: number = 3000;

  // DI(依存性の注入)
  // DOMへのアクセスが可能となる
  constructor(private element: ElementRef) {}

  // クリックイベントを受け取り処理を実行
  @HostListener('click') public onClick() {
    console.log('要素をdisabledにします');
    // 受け取ったHTML要素のdisabled属性をtrueにして、非活性にする
    this.element.nativeElement.disabled = true;
    // my-disabledというクラス名を追加し、CSSでデザインを追加 ※なくてもOK
    this.element.nativeElement.classList.add('my-disabled');

    // timerに値がある → timerの値を設定
    // timerに値がない → TIMERの値を設定
    const interval = this.timer || this.TIMER;

    // 指定した時間が経過したら処理を実行
    setTimeout(() => {
      // disabled属性をfalseにして活性状態に戻す
      this.element.nativeElement.disabled = false;
      // 追加したクラス名を削除
      this.element.nativeElement.classList.remove('my-disabled');
    }, interval);
  }
}
@Input() timer!: number;

Inputデコレータを使って引数を受けとります。

const interval = this.timer || this.TIMER;

この部分が少しわかりにくいかもしれないですが、
JavaScript(TypeScript)のショートハンドで、
やっていることとしては以下と同じです。

if (this.timer) {
  interval = this.timer;
} else {
  interval = this.TIMER;
}
appPreventDoubleClickをHTMLの属性として付与することで機能するよ!
Inputデコレータについて詳しく知りたい方はこちら!

【Angular】子コンポーネントに値を渡そう!【props】

app.component.css

.my-disabled {
  background-color: pink;
}
非活性の際にはボタンがピンクになるよ!

app.component.html

<button appPreventDoubleClick>クリック!引数なし</button>
<br />
<button appPreventDoubleClick [timer]="1000">クリック!引数あり</button>
引数ありの方は待機時間が1000ミリ秒になるよ!

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { PreventDoubleClickDirective } from './directive/prevent-double-click.directive';

@NgModule({
  declarations: [
    AppComponent,
    PreventDoubleClickDirective
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

動作確認

これで任意にインターバルを設定できる連打防止ディレクティブができたよ!

GitHubのサンプルコード

今回作ったものはGitHubにあげているので
うまく動作しなかった方は是非ダウンロードしてみてください。

GitHub - same-hack/Angular-Directive-augument
Contribute to same-hack/Angular-Directive-augument development by creating an account on GitHub.

まとめ

  • ディレクティブとは、HTML要素に属性として記述する事でDOMの操作を可能とするクラス
  • 要素に一時的にdisabled属性を付与することで連打防止機能が作成出来る
  • inputデコレータを使うことで引数を渡すことが可能

満足いただけたら、1クリックなのでSNSフォローしてもらえると嬉しいです🦈

タイトルとURLをコピーしました