Angular 6 *ngFor display different styles for first, odd, even and last

Viewed 8722

I am learning Angular 6 and just trying to put togheter some of the stuff I have learned and I am currently running into an issue that I cannot find an answer to. I am trying to change the style of a LI using *ngFor depending if the index is First, Last, Odd or Even. So far everything works but I can't figure out how to do it for the Last because everything I add a new object to my list, it is obviously the last so it render the color for the last.

I understand how to do it but the real problem is that I am adding stuff dynamicly to my list from a form and I'm not sure how to evaluate the Last so that the others become to right color.

Keep in mind that I am still a newb and it might look messy and I also understand that some client-side validations I am doing are probably not optimal or required since HTMl5 but I made it to learn.

Here is my code for my component HTML

>

<h1>List of courses :</h1><br>
<div *ngIf="courses.length > 0; then coursesList else noCourses"></div>

<ng-template #coursesList>
  <h2>List of Courses :</h2>
  <ul *ngFor="let course of courses; index as i;">
    <li [ngStyle]="{'background-color':getColor(i)}" style="color: white;">
      <strong>Index : </strong>{{i}} <strong>ID : </strong>{{course.id}} <strong>Name</strong> : {{course.name}}
      <button (click)="onRemove(i)">Remove</button>
      <button (click)="onModify(i)">Modify</button>
    </li>
  </ul>
</ng-template>
<ng-template #noCourses>
  <h5>There are no courses in this list. Use the form bellow to add some.</h5>
</ng-template>

<div (keyup.enter)="onAdd()">
  <span>ID : <input type="number" (keypress)="checkNumber($event)" [(ngModel)]="fields.id" placeholder="Enter an ID"></span>
  <span>Name : <input type="text" [(ngModel)]="fields.name" placeholder="Enter a NAME"></span>
  <button (click)="onAdd()">Add</button>
  <button (click)="onClear()">Clear</button>
</div>
<div *ngIf="isNotNumber" style="background-color: red; color:black"><strong>ID can only be numbers !</strong></div>
<div *ngIf="noValues" style="background-color: red; color:black"><strong>Please fill all fields !</strong></div>
<div *ngIf="noModifyValues" style="background-color: red; color:black"><strong>To modify enter all informations!</strong></div>

Code for .TS

>

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})


export class AppComponent {
  noValues: boolean;
  noModifyValues: boolean;
  isNotNumber: boolean;
  fields: Courses = {id: null, name: null};
  courses: Array<Courses> = [];
  viewMode: string = null;

  checkNumber($event) {
    if ($event.keyCode != 13) {
      isFinite($event.key) ? this.isNotNumber = false : this.isNotNumber = true;
    }
  }

  onAdd() {

    if (!this.fields.id || !this.fields.name) {
      this.noValues = true;
    } else {
      this.courses.push({id: this.fields.id, name: this.fields.name});
      this.fields.id = null;
      this.fields.name = null;
      this.noValues = false;
    }
  }

  onRemove(i) {
    this.courses.splice(i, 1);
  }

  onClear() {
    this.courses = [];
    this.fields.id = null;
    this.fields.name = null;
    this.noValues = false;
  }

  onModify(i) {
    if (!this.fields.id || !this.fields.name) {
      this.noModifyValues = true;
    } else {
      this.courses[i].name = this.fields.name;
      this.courses[i].id = this.fields.id;
      this.noModifyValues = false;

    }
  }

  getColor(i){
    if (i % 2 === 0 && i != 0){i = 'odd';}
    switch (i) {
      case i = 0 : return 'orange';
      case i = 'odd' : return 'blue';
    }
    return 'red';
  }
}
interface Courses {
  id: number;
  name: string;
}

Image of the code in action for better understanding.

4 Answers

If you only want change the background-color you can use [style.background-color] and you can use ternary operator in the .html

<ul *ngFor="let course of courses; let index=i;
                                   let odd=odd;
                                   let last=last;
                                   let first=first">
    <li [style.backgound-color]="first?'orange':last?'purple':odd?'blue':'red'">
          ...
    </li>
</ul>

Try something like this

getColor(i){
    if (i % 2 === 0 && i != 0){i = 'odd';}
    if (this.courses && (this.courses.length - 1 === i)) {i = 'last'}
    switch (i) {
      case i = 0 : return 'orange';
      case i = 'odd' : return 'blue';
    }
    return 'red';
  }

Hope it works - Happy coding !!

Thanks Rahul. The part I was missing is evaluating if there is something in courses. However, I had to had a few more lines to Odd and Last as follow :

getColor(i){
    if (this.courses && i != 0 && (this.courses.length - 1 === i)) {i = 'last'}
    if (i % 2 === 0 && i != 0 && i != 'last'){i = 'odd';}
    switch (i) {
      case i = 0 : return 'orange';
      case i = 'odd' : return 'blue';
      case i = 'last' : return 'purple';
    }
    return 'red';
  }

Quick question. It seems like a whole lot of IF and && and checking specific things. Is that the way to do it properly?

You could use if else ladder instead of mixing up if else and switch and assignments like given below

getColor(i)
{
  if(this.courses)
  {
  if(i==0)
      return "orange";
  else if(i==this.courses.length-1)
      return "purple";
  else if (i%2==0)
      return "red";
  else
      return "blue";
  }
}
Related