簡體   English   中英

如何簡潔地刪除和添加 class in Angular renderer2

[英]How to remove and add class in Angular renderer2 succinctly

是否可以在兩行中簡潔地從元素中添加和刪除 class 而不是編寫一大堆 if else 語句

你能做這個嗎? (雖然它對我不起作用。)

constructor(private renderer: Renderer2,private elRef: ElementRef) {
   const action = isDisabled ? 'addClass' : 'removedClass';
   this.renderer[action](div, 'disabled');
}

代替

if (isDisabled) {
   this.renderer.addClass(div, 'disabled');
} else {
   this.renderer.removeClass(div, 'disabled');
}

有可能做到

const action = isDisabled ? 'addClass' : 'removeClass';
this.renderer[action](div, 'disabled');

甚至

this.renderer[isDisabled ? 'addClass' : 'removeClass'](div, 'disabled');

它是removeClass ,而不是刪除d 而這正是為什么不應該這樣做的原因。

括號表示法禁用類型檢查,因此可以訪問不存在的屬性而不會觸發類型錯誤。

另一個原因是代碼可能更難閱讀。

您可以使用ngClass指令( https://angular.io/api/common/NgClass )來實現這一功能:

<div [ngClass]="disabled ? 'disabled' : ''"></div>

如果需要在組件類中使用renderer來實現此目的,可以使用:

this.renderer.setAttribute(div, 'class', this.disabled ? 'disabled' : '');

看到這個工作Stackblitz兩種方法演示: https ://stackblitz.com/edit/angular-7ywg27

解決方案:

創建一個自定義指令,以切換相關的 class,以便稍后可以在模板上簡潔地使用它。 在這些示例中,我將通過下拉菜單執行此類操作(特別是通過帶有 class 'btn-group' 的包裝 div,其中包含一個按鈕和一個 UL 元素)。

筆記:

  1. 我在這些示例中使用 Angular 13。
  2. 我在這些示例中也使用了 Bootstrap 3(特別是 3.4.1),因此此處相關的 class 是“打開的”。 對於 bootstrap 4 或 5,您必須改用“show”。
  3. 顯然,每個指令在使用前都必須在 App.module 中注冊(聲明)。

選項 # 1:使用 HostBinding。

文件: src/app/directives/dropdown-host-binding/dropdown-host-binding.directive.ts

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

@Directive({
  selector: '[appDropdownHostBinding]'
})
export class DropdownHostBindingDirective {
  private wasInsideTheElement = false;
  @HostBinding('class.open') isOpen = false;

  constructor() {
  }

  @HostListener('click') toggleOpen(eventData: Event): void {
    this.isOpen = !this.isOpen;
    this.wasInsideTheElement = true;
  }

  @HostListener("document:click") clickOut(): void {
    if (!this.wasInsideTheElement) {
      this.isOpen = false;
    }
    this.wasInsideTheElement = false;
  }
}

用法:

    <!-- Using a custom Dropdown Directive using HostBinding -->
    <div appDropdownHostBinding class="btn-group">
      <button type="button" class="btn btn-primary dropdown-renderer-toggle">
        Manage recipe <span class="caret"></span>
      </button>

      <ul class="dropdown-menu">
        <li><a href="#">Add to Shopping List</a></li>
        <li><a href="#">Edit Recipe</a></li>
        <li><a href="#">Delete Recipe</a></li>
      </ul>
    </div>

選項 # 2:使用 ElementRef + Renderer2。

文件: src/app/directives/dropdown-renderer/dropdown-renderer.directive.ts

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

@Directive({
  selector: '[appDropdownRenderer]'
})
export class DropdownRendererDirective {
  private wasInsideTheElement = false;
  isOpen = false;

  constructor(private elementRef: ElementRef, private renderer: Renderer2) {
  }

  @HostListener('click') mouseClick(eventData: Event): void {
    this.isOpen = !this.isOpen;
    this.executeAction();
    this.wasInsideTheElement = true;
  }

  @HostListener("document:click") clickOut(): void {
    if (!this.wasInsideTheElement) {
      this.isOpen = false;
      this.executeAction();
    }
    this.wasInsideTheElement = false;
  }

  private executeAction(): void {
    const action = this.isOpen ? 'addClass' : 'removeClass';
    this.renderer[action](this.elementRef.nativeElement, 'open');
  }
}

用法:

    <!-- Using a custom Dropdown Directive using ElementRef & Renderer2  -->
    <div appDropdownRenderer class="btn-group">
      <button type="button" class="btn btn-primary dropdown-toggle">
        Manage recipe <span class="caret"></span>
      </button>

      <ul class="dropdown-menu">
        <li><a href="#">Add to Shopping List</a></li>
        <li><a href="#">Edit Recipe</a></li>
        <li><a href="#">Delete Recipe</a></li>
      </ul>
    </div>

選項 # 3:組合 HostBinding + ElementRef。

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

@Directive({
  selector: '[appDropdownHostBindingSimpler]'
})
export class DropdownHostBindingSimplerDirective {
  @HostBinding('class.open') isOpen = false;

  constructor(private elementRef: ElementRef) {
  }

  @HostListener('document:click', ['$event']) toggleOpen(event: Event) {
    this.isOpen = this.elementRef.nativeElement.contains(event.target) ? !this.isOpen : false;
  }
}

用法:

    <!-- Using a custom Dropdown Directive using HostBinding & ElementRef  -->
    <div appDropdownHostBindingSimpler class="btn-group">
      <button type="button" class="btn btn-primary dropdown-toggle">
        Manage recipe <span class="caret"></span>
      </button>

      <ul class="dropdown-menu">
        <li><a href="#">Add to Shopping List</a></li>
        <li><a href="#">Edit Recipe</a></li>
        <li><a href="#">Delete Recipe</a></li>
      </ul>
    </div>

視覺結果(所有這些都相同):

在此處輸入圖像描述

Angular 太棒了!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM