1

Goal: I want to change the text to red based on a condition, when looping through an object (using ngClass in Angular 6)

This was working for me, but all of a sudden is no longer working.

I've tried printing to console... and I am getting In Progress false Complete true

(Expected) Which makes me think the first one should be red, and the second one black. (Actual) But they are both black.

I've also tried resetting the variable isComplete back to false if it got to the else condition. Angular: conditional class with *ngClass

HTML:

<div class="row" *ngFor="let lesson of lessons">
    <div>
        <div class="flex">
            <div>
               Status: <span [ngClass]="(isComplete!=true)?'text-red':''">{{ lesson.Status }}</span>
            </div>
        </div>
    </div>
</div>

TypeScript:

private isComplete: boolean = false;

this.lessons.forEach(element => {                           
    if (element.Status == "Complete") {
        this.isComplete = true;
        element.Status = this.var1;
    }
    else {
        element.Status = this.var2;
    }
});
seesharp
  • 101
  • 1
  • 14

3 Answers3

1

I see that you're assigning the isComplete value to a global variable. This is shared by all lessons, so with your current logic, they will all be red or all black.

I would refactor to have the isComplete exist as a property within the individual lesson, this way you'll have a separate value for each lesson.

You can update the view model after it arrives from server. As long as you can determine whether is complete or not there shouldn't be any reason why you cant extend the VM.

processedLessons = []

this.lessons.forEach(lesson => {                           
    if (lesson.Status == "Complete") {
        lesson.isComplete = true;
        lesson.Status = this.var1;
        processedLessons.push(lesson);
    }
    else {
        lesson.Status = this.var2;
    }
});

After that I would refactor my template to this:

<div class="row" *ngFor="let lesson of processedLessons">
    <div>
        <div class="flex">
            <div>
               Status: <span [ngClass]="{'red': !lesson.isComplete, 'black': lesson.isComplete }">{{ lesson.Status }}</span>
            </div>
        </div>
    </div>
</div>

Or just do this using your original JavaScript...

<div class="row" *ngFor="let lesson of lessons">
    <div>
        <div class="flex">
            <div>
               Status: <span [ngClass]="{'red': lesson.status !== 'Complete', 'black': lesson.status === 'Complete' }">{{ lesson.Status }}</span>
            </div>
        </div>
    </div>
</div>
A. Figueroa
  • 215
  • 1
  • 8
  • Yes you are correct I ended up noticing this. I'd prefer not to add it to Lesson interface since this is coming from the database. I will brainstorm if there are any other ways around this. One that I found, which is not the cleanest is to change the ngClass to make sure Two things are not true, instead of one. I tested and it works, but I'd prefer a cleaner way. – seesharp Feb 21 '19 at 17:50
  • I refactored to allow a potentially cleaner solution without having to update your DB models. – A. Figueroa Feb 21 '19 at 18:40
  • Would creating a new object (processedLessons) and placing the original data in that object be a better solution than doing two conditional checks in the loop (lesson.Status!='Complete' && item.Status!='Otherthing' ? – seesharp Feb 21 '19 at 21:47
  • Not really. But I think you can simplify it even further, by removing the loop and just binding to the ngclass like in the last code snippet. [ngClass]="{'red': lesson.status !== 'Complete', 'black': lesson.status === 'Complete' }" – A. Figueroa Feb 22 '19 at 18:10
  • @A.Figueroa I tried your above solution. The first condition is ignored and only the second condition is factored in. I tried swapping the conditions, still has the same behavior, only the second condition is factored in. – Tora Tora Tora Mar 10 '23 at 04:46
0

if u check the document: https://angular.io/api/common/NgClass

I don't see any use case like yours anyway, this how u should do it:

<span [ngClass]="{'text-red': !isComplete}">{{ lesson.Status }}</span>

also, check the document u will more useful use.

Y_Moshe
  • 424
  • 1
  • 5
  • 11
  • there is no one thruth: check the link https://stackoverflow.com/questions/35269179/angular-conditional-class-with-ngclass – jcuypers Feb 20 '19 at 20:34
  • I don't get u, the answer there is exactly like mine, not like I copy it, what u want me to see there? – Y_Moshe Feb 20 '19 at 20:49
  • i just wanted to say that there are more ways then shown in the first doc. not important – jcuypers Feb 20 '19 at 20:51
0
<span [ngClass]="{'text-red': lesson.Status == 'Complete'}">{{ lesson.Status }}</span>