问题
Hi I was in the midst of creating a wizard/step component.
How can I use the ngClass
to return css classes based on ->
?
I have 5 steps, let's say the user is in the 3rd step. All the previous steps should return a css class named active
and the current step (step 3) returns css class active
and all the steps after step 3 should return inactive
css class.
<div class="step actived">
<span [ngClass]="displayActiveness()">Step 1
</span>
</div>
<div class="divider"></div>
<div class="step" [ngClass]="displayActiveness()">
<span>Step 2
</span>
</div>
.....
TS:
displayActiveness(status) {
if (this.statusSelected === 'step3') {
return 'active';
} else if (
this.statusSelected === 'step4' || this.statusSelected === 'step5'){
return 'inactive';
}
else if (
this.statusSelected === 'step1' || this.statusSelected === 'step2'){
return 'actived';
}
}
I am stuck. Can someone please help me on this. Thanks in advance.
回答1:
Why not set your statusSelected to number and it would be easy to manage?
TS:
statusSelected: number = 1; //step 1 by default
....
displayActiveness(status) {
if (this.statusSelected === status) {
return 'active';
}
if (this.statusSelected > status) {
return 'actived';
}
if (this.statusSelected < status) {
return 'inactive';
}
}
HTMl:
<div class="step" [ngClass]="displayActiveness(1)">
<span>Step 1</span>
</div>
<div class="divider"></div>
<div class="step" [ngClass]="displayActiveness(2)">
<span>Step 2</span>
</div>
with this, next step could be only:
nextStep() {
this.statusSelected++;
}
回答2:
Alternatively, You can iterate over loop and set active class to your step like this -
<div class="step" [ngClass]='{"active" : activeClassList[0]}'>
<span>Step 0</span>
</div>
<div class="step" [ngClass]='{"active" : activeClassList[1]}'>
<span>Step 1</span>
</div>
<div class="step" [ngClass]='{"active" : activeClassList[2]}'>
<span>Step 2</span>
</div>
<div class="step" [ngClass]='{"active" : activeClassList[3]}'>
<span>Step 3</span>
</div>
<div class="step" [ngClass]='{"active" : activeClassList[4]}'>
<span>Step 4</span>
</div>
<div class="step" [ngClass]='{"active" : activeClassList[5]}'>
<span>Step 5</span>
</div>
settingActiveClass() {
for(let i=0; i < this.userLevel; i++) {
this.activeClassList[i] = 'active';
}
}
working example
回答3:
Check the following example.
component.html
<ul>
<li *ngFor="let step of steps; let i = index">
<span class="step" [ngClass]="displayActiveness(i)">
{{step}}
</span>
<button (click)="chooseStep(i)">Click me</button>
</li>
</ul>
component.ts
export class AppComponent {
name = 'Angular 6';
currentStep = 0;
steps = ['step1', 'step2', 'step3', 'step4', 'step5'];
chooseStep(index) {
this.currentStep = index;
}
displayActiveness(index) {
console.log('displayActiveness called')
if (index > this.currentStep) {
return 'inactive';
} else {
return 'active';
}
}
}
When you check the console, you'll see displayActiveness
method gets called 10 times when you click on Click me
button. This is because of angular change detection mechanism. When something happens to trigger change detection, angular will go through your template and call everything. So, generally it's not a good idea to call functions within templates. But, let's say you absolutely need to do so. Then, you can use pipes.
Check this second example
In this example, I moved the logic of displayActiveness
method to a Pipe, so that it only gets executed when the inputs change. It may not differ much in your example but think of a much more complicated method. You would not want angular to call your complicated method every time user does something.
active.pipe.ts
@Pipe({
name: 'activePipe'
})
export class ActivePipe implements PipeTransform {
transform(index, currentStep) {
console.log('pipe called')
if (index > currentStep) {
return 'inactive';
} else {
return 'active';
}
}
}
Changing ngClass
to following
<span class="step" [ngClass]="i | activePipe: currentStep">
{{step}}
</span>
来源:https://stackoverflow.com/questions/50226800/angular-2-ngclass-function