Angular:仅在当前单击的按钮上切换活动 class(不使用 *ngFor)

Angular: Toggle active class on only button the current clicked button (not using *ngFor)

我想弄清楚如何才能仅在 单击的按钮:

上切换 active class

这是我当前的代码...

<div class="btn-group">
  <button class="btn btn-secondary" [ngClass]="{ 'active' : isActive }" (click)="isActive = !isActive" type="button">Premier bouton</button>
  <button class="btn btn-secondary" [ngClass]="{ 'active' : isActive }" (click)="isActive = !isActive" type="button">Second bouton</button>
  <button class="btn btn-secondary" [ngClass]="{ 'active' : isActive }" (click)="isActive = !isActive" type="button">Troisième bouton</button>
  <button class="btn btn-secondary" [ngClass]="{ 'active' : isActive }" (click)="isActive = !isActive" type="button">Quatrième bouton</button>
</div>

...这是结果:

不使用*ngForng-repeat原则。我知道我需要 隔离 每个按钮。我该怎么做?

this. 添加到 isActive 不起作用:this.isActive.

您应该如下使用

clickedButton(event){console.log(event)
    let temp= event.srcElement.parentNode;
    for(let i = 0; i < temp.childNodes.length; i++){
      if(temp.childNodes[i].nodeName === 'BUTTON'){
      if(temp.childNodes[i].classList.contains('active')){
        temp.childNodes[i].classList.remove('active');
      }  }
    }
    event.srcElement.classList.add('active')

  }

<div class="btn-group">
  <button class="btn btn-secondary"   (click)="clickedButton($event)" type="button">Premier bouton</button>
  <button class="btn btn-secondary"   (click)="clickedButton($event)" type="button">Second bouton</button>
  <button class="btn btn-secondary"   (click)="clickedButton($event)" type="button">Troisième bouton</button>
  <button class="btn btn-secondary"   (click)="clickedButton($event)" type="button">Quatrième bouton</button>
</div>

LIVE DEMO

我只想为每个按钮使用一个唯一的字符串。例如:

<div class="btn-group">
  <button class="btn btn-secondary" [class.active]="isActive('btn1')" (click)="setActive('btn1')" type="button">Premier bouton</button>
  <button class="btn btn-secondary" [class.active]="isActive('btn2')" (click)="setActive('btn2')" type="button">Second bouton</button>
  <button class="btn btn-secondary" [class.active]="isActive('btn3')" (click)="setActive('btn3')" type="button">Troisième bouton</button>
  <button class="btn btn-secondary" [class.active]="isActive('btn4')" (click)="setActive('btn4')" type="button">Quatrième bouton</button>
</div>

您的 setActiveIsactive 函数看起来像这样:

this.setActive = function (buttonName){
  this.activeButton = buttonName;
}
this.isActive = function (buttonName){
  return this.activeButton === buttonName;
}

因此每个按钮都会传递其名称,这只是一些唯一的字符串。该字符串将被保存为一个变量,并将用于确定是否应应用活动 class。

您还会注意到,您可以通过绑定到 class 名称来切换单个 classes。就像我上面为活动 class 所做的那样,它可以与 [class.active].

绑定

简单,就用Event Delegation.

Component.html:

<div class="btn-group" (click)="onButtonGroupClick($event)">
  <button class="btn btn-secondary" type="button">Premier bouton</button>
  <button class="btn btn-secondary" type="button">Second bouton</button>
  <button class="btn btn-secondary" type="button">Troisième bouton</button>
  <button class="btn btn-secondary" type="button">Quatrième bouton</button>
</div>

Component.ts/.js:

  onButtonGroupClick($event){
    let clickedElement = $event.target || $event.srcElement;

    if( clickedElement.nodeName === "BUTTON" ) {

      let isCertainButtonAlreadyActive = clickedElement.parentElement.querySelector(".active");
      // if a Button already has Class: .active
      if( isCertainButtonAlreadyActive ) {
        isCertainButtonAlreadyActive.classList.remove("active");
      }

      clickedElement.className += " active";
    }

  }

实例:https://plnkr.co/edit/EE4dOMgpY8QA2qZXjMiW?p=preview

您使用 [ngClass] 所做的事情很好,但问题出在您的 (click) 事件上。当您单击同一个按钮两次时,表达式 isActive = !isActive 给出错误。

因此,您可以对按钮的每个单击事件使用不同的方法集。

在你的.ts文件中,如下写

isValue: number = 0;  // This is a class property. By initializing with a value, you can set the default button highlighted

toggle1() { this.isValue = 1; }
toggle2() { this.isValue = 2; }
toggle3() { this.isValue = 3; }
toggle4() { this.isValue = 4; }

然后在您的 html 文件中,更改如下,

<button class="btn btn-secondary" [ngClass]="{ 'active' : isValue == 1 }" (click)="toggle1()" type="button">Premier bouton</button>
<button class="btn btn-secondary" [ngClass]="{ 'active' : isValue == 2 }" (click)="toggle2()" type="button">Second bouton</button>
<button class="btn btn-secondary" [ngClass]="{ 'active' : isValue == 3 }" (click)="toggle3()" type="button">Troisième bouton</button>
<button class="btn btn-secondary" [ngClass]="{ 'active' : isValue == 4 }" (click)="toggle4()" type="button">Quatrième bouton</button>

在这里,我只更改了 (click) 事件和 [ngClass] 。

你也可以做到:

在您的 .ts 文件中

isValue: number = 0;

toggle(num) { this.isValue = num; }

并在您的 html 文件中更改如下

<button class="btn btn-secondary" [ngClass]="{ 'active' : isValue == 1 }" (click)="toggle(1)" type="button">Premier bouton</button>
<button class="btn btn-secondary" [ngClass]="{ 'active' : isValue == 2 }" (click)="toggle(2)" type="button">Premier bouton</button>
<button class="btn btn-secondary" [ngClass]="{ 'active' : isValue == 3 }" (click)="toggle(3)" type="button">Premier bouton</button>
<button class="btn btn-secondary" [ngClass]="{ 'active' : isValue == 4 }" (click)="toggle(4)" type="button">Premier bouton</button>

并在您的 css 文件中更改如下:

.active { background-color: gray; }

由于您正在寻找更多 'Angular Way' 继续,这是另一种方法,使用 Service 结合 RxJs .这个想法是有一个MenuService,它将活动按钮引用存储为Subject。您的按钮将能够订阅 Subject,并在更改时接收新的按钮引用。在按钮模板中测试该值将允许您应用或不应用活动 class.

这个例子可以用更丰富的功能来阐述,但为了解释的目的,我会尽可能简单地回答OP问题。

首先,创建一个新的 Interface(或 Class,如您所愿)来定义您的按钮模型。在这种情况下,我将其称为 MenuItem在这个例子中,MenuItem.ts存储在这里/src/app/_models/

MenuItem.ts

export interface MenuItem {
   label: string;
   routerLink: string;
}

然后,创建 MenuService 服务。在这里,您需要声明一个 BehaviourSubject 来存储单击按钮的引用。使用此方法,您将能够在每次单击新按钮并成为活动按钮时调用 .next()

menu.service.ts

import { MenuItem } from 'src/app/_models/MenuItem'
import { BehaviorSubject } from 'rxjs';

@Injectable({
    providedIn: 'root',
})
export class MenuService {
    $activeButton: BehaviorSubject<MenuItem> = new BehaviorSubject<MenuItem>({} as MenuItem);

    constructor() {}
}

接下来,创建一个将 MenuItem 用作 Input() 属性 的组件。不要忘记注入 MenuService。因此,您将能够订阅服务中存储的当前活动按钮。

menu.button.component.ts

@Component({
    selector: 'app-menu-button',
    templateUrl: './menu-button.component.html',
    styleUrls: ['./menu-button.component.scss']
})
    
export class MenuButton implements OnInit {
    @Input() menuItem: MenuItem = {} as MenuItem;
    isActive: boolean = false;

    constructor(private menuService: MenuService) {}

    ngOnInit(): void {
        this.menuService.$activeButton.subscribe((activeButton) => this.isActive = this.menuItem === activeButton);
    }

    setActive() {
       this.menuService.$activeButton.next(this.menuItem);
    }

}

您现在可以测试按钮的 isActive 属性 并应用或不应用所需的 class。不要忘记捕获 click 事件并通过调用 next() 并使用上面编写的 setActive() 方法传递新的 menuItem 值来更新 $activeButton 值。

menu.button.component.html

<button [routerLink]="this.menuItem.routerLink" [ngClass]="{ active: this.isActive }" (click)="this.setActive()">{{ this.menuItem.label }}</button>