自定義屬性型 Directive(三):輸入參數與進階用法

為 Directive 添加輸入參數

Directive 和 component 一樣,可以接收輸入參數來增強其可重用性。

基本輸入用法

可以使用 input() 函數來定義輸入屬性:

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

@Directive({
  selector: 'a[appSafeLink]',
  standalone: true,
  host: {
    '(click)': 'onConfirmLeavePage($event)',
  },
})
export class SafeLinkDirective {
  // 'myapp' 為預設值
  queryParam = input('myapp');
  
  onConfirmLeavePage(event: MouseEvent) {
    const wantsToLeave = window.confirm('Do you want to leave this app?'); // true 或 false
    
    if (wantsToLeave) {
      const address = (event.target as HTMLAnchorElement).href;
      (event.target as HTMLAnchorElement).href = 
        address + '?from=' + this.queryParam();
      return;
    }
    event.preventDefault();
  }
}

在 HTML 中使用:

<a href="https://angular.dev" appSafeLink queryParam="myapp-docs-link">Angular Documentation</a>

注意,queryParam 沒有使用方括號 [],因為這裡傳遞的是一個固定的字串,而不是來自 component class 的動態表達式。

使用別名簡化 HTML

可以為 input 定義別名,以簡化在 HTML 中的使用方式:

queryParam = input('myapp', { alias: 'appSafeLink' });

HTML 使用變得更簡潔:

<a href="https://angular.dev" appSafeLink="myapp-docs-link">Angular Documentation</a>

這樣,指令選擇器本身也能接收參數值,不需要額外的屬性。

使用依賴注入

指令可以利用 Angular 的依賴注入系統來訪問 host 元素和其他服務。

注入宿主元素

使用 inject() 函數可以直接獲取指令所附加的 DOM 元素:

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

@Directive({
  selector: 'a[appSafeLink]',
  standalone: true,
  host: {
    '(click)': 'onConfirmLeavePage($event)',
  },
})
export class SafeLinkDirective {
  queryParam = input('myapp', { alias: 'appSafeLink' });
  
  // 注入 hostElementRef
  private hostElementRef = inject<ElementRef<HTMLAnchorElement>>(ElementRef);
  
  onConfirmLeavePage(event: MouseEvent) {
    const wantsToLeave = window.confirm('Do you want to leave this app?');
    
    if (wantsToLeave) {
      // 使用 hostElementRef 直接訪問和修改 DOM
      const address = this.hostElementRef.nativeElement.href;
      this.hostElementRef.nativeElement.href = 
        address + '?from=' + this.queryParam();
      return;
    }
    event.preventDefault();
  }
}

使用 ElementRef 的好處:

  • 不需要類型轉換,因為我們在注入時已經指定了元素類型

  • 直接訪問真實的 DOM 元素

  • 程式碼更加簡潔和類型安全

其他可注入服務

除了 ElementRef,指令還可以注入其他 Angular 服務:

  • ChangeDetectorRef:管理變更檢測

  • ...

Last updated