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>
...这是结果:
我不使用*ngFor
或ng-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>
我只想为每个按钮使用一个唯一的字符串。例如:
<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>
您的 setActive
和 Isactive
函数看起来像这样:
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";
}
}
您使用 [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>
我想弄清楚如何才能仅在 单击的按钮:
上切换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>
...这是结果:
我不使用*ngFor
或ng-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>
我只想为每个按钮使用一个唯一的字符串。例如:
<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>
您的 setActive
和 Isactive
函数看起来像这样:
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";
}
}
您使用 [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>