Help with ionList of cards and ngClass


#1

Hi everyone!

I am new to this forum, first time posting, so I apologize if they way of writing this isn’t proper.

I am trying to create a list of cards, and each card comes from an array of subjects, based on a course, day and the hour you choose. There are cases where there is only 1 subject, but the could be more than one.

Then each card has three buttons, great, good and bad, and depending on which button you choose, the background of the card-header changes to one color or another; blue, green and red in this case and order.

I save each subject and it’s color properly, but when there are more than one cards, it automatically shows the same color for all of them, even knowing each of them has different colors.

I bet this is an issue related to ngClass, and I would like someone to help me if could be possible, thanks in regard!

This is my code for html:

  <ion-list *ngIf="horaSeleccionada">
    <ion-item-sliding>
      <ion-item *ngFor="let asignatura of asignaturas">
        <ion-card>
          <ion-card-header [ngClass]="showColor()">
            <ion-card-title text-center>
              {{asignatura}}
            </ion-card-title>
          </ion-card-header>

          <ion-row style="height: 8px"></ion-row>

          <ion-card-content align-items-center>

            <button *ngFor="let valoracion of listaValoraciones" clear ion-button color="{{valoracion.color}}"
                    (click)="cambiarValoracion(asignatura, valoracion.nombre)" icon-start>
              <ion-icon name="{{valoracion.icono}}"></ion-icon>
              {{valoracion.nombre}}
            </button>
          </ion-card-content>
        </ion-card>
      </ion-item>
    </ion-item-sliding>
  </ion-list>

I have saved an array of Asignaturas(Subjects), which includes name and value of each subject. Then using showColor and cambiarValoracion, I compare the string result of {{asignatura}} with the name of each array item, and once I have found it I change its color.

This way I am able to save each subject with it’s color, but again if there are more than one cards they show all the same color. If I chose a day and an hour where there is only one the color is proper.

These are my methods showColor() and cambiarValoracion();

  showColor() {

        if (this.asignaturaSeleccionada.valoracion === "") {
          return 'blanco';
        }

        if (this.asignaturaSeleccionada.valoracion === "Estupenda") {
          return 'azul';
        }

        if (this.asignaturaSeleccionada.valoracion === "Pasable") {
          return 'verde';
        }

        if (this.asignaturaSeleccionada.valoracion === "Horrorosa") {
          return 'rojo';
        }
  }

  cambiarValoracion(asignatura, valoracion) {

    this.asignatura2 = asignatura;
    for (let i = 0; i < this.listaAsignaturas.length; i++) {
      if (this.asignatura2.match(this.listaAsignaturas[i].nombre)) {
        this.asignaturaSeleccionada = this.listaAsignaturas[i];
        this.asignaturaSeleccionada.valoracion = valoracion;
      }
    }

    console.log(this.asignaturaSeleccionada);
    this.showColor();
  }

#2

You have two problems here.

The first is that you are calling showColor without changing anything else, so naturally it will return the same thing on each iteration of the loop.

The second, and more important, is that showColor should not exist in the first place. Never call functions from template expressions that are evaluated by Angular change detection: they get called a zillion times for no reason. Instead, make color a property of each element of the asignaturas list, so that you can write [ngClass]="asignatura.color". Change whatever logic determines the various colors to proactively update that color property whenever external factors change (like the user making a new selection), instead of waiting around and figuring it on-demand in template loops.


#3

Alright. Got your idea.

In this case asignaturas have it is own name and a string called valuation.

What I do is once I press each button, asignatura valuation changes to nice, good or bad.

Then I have a list of valuation, which has name, color and icon. I compare asignatura valuation name with the list of valuation items, and once I find the valuation I change header background to the color of valuation.

Supposedly asignatura should not have a color property, just its name and valuation. So how would you manage it?

Thanks!


#4

If you just convert all your valoracions into lower-case, you could just use them directly as classes.

[ngClass]="asignatura.valoracion"
.estupenda {
  background-color: blue;
}