htmlcssangularrating

Stars rated selection in an Angular Project


I have an Angular project with a component like this:

            <div class="stars-container mt-2">
                <div *ngFor="let star of starsArray; let i = index" class="star">
                    <svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24">
                        <path fill="#ffffff"
                            d="m7.69 19.346l1.614-5.33L5.115 11h5.216L12 5.462L13.67 11h5.215l-4.189 3.015l1.614 5.331L12 16.07z" />
                    </svg>
                </div>
            </div>

Where startsArray is:

starsArray: boolean[] = new Array(5);

The SCSS is:

.stars-container {
    display: flex;
    justify-content: left;
    align-items: center;
    gap: .7rem;
    cursor: pointer;
    flex-direction: row-reverse;

    .star {
        transition: .3s ease;

        svg {
            width: 3rem;
            height: auto;

            path {
                fill: $gris; // Color de las estrellas no seleccionadas
                transition: fill .3s ease; // Transición suave del color
            }
        }

        &:hover~.star svg path {
            fill: $primario; // Color de las estrellas seleccionadas al hacer hover
        }

        &:hover svg path {
            fill: $primario; // Color de la estrella seleccionada al hacer hover
        }
    }
}

.star:hover svg path,
.star:hover~.star svg path,
.star.highlighted svg path {
    fill: $primario;
}

At the moment I have achieved that when I make hover on a star, the left stars also change the color. Nevertheless, I would like to make that when I press a star, all the stars on the left and the clicked star change color permanently (permanently in the browser session, no with Data Base).

I have tried several things but nothing works.


Solution

  • Please find below working stackblitz and code

    import { CommonModule } from '@angular/common';
    import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
    
    @Component({
      selector: 'app-star-rating',
      standalone: true,
      template: `
        <div class="stars-container mt-2">
            <div *ngFor="let star of starsArray; let i = index" class="star" (click)="selectRating(i)" [ngClass]="{'selected': 5 - rating <= i}">
                <svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24">
                    <path fill="#00000"
                        d="m7.69 19.346l1.614-5.33L5.115 11h5.216L12 5.462L13.67 11h5.215l-4.189 3.015l1.614 5.331L12 16.07z" />
                </svg>
            </div>
        </div>
      `,
      styles: `
      .stars-container {
        display: flex;
        justify-content: left;
        align-items: center;
        gap: .7rem;
        cursor: pointer;
        flex-direction: row-reverse;
    
        .star {
            transition: .3s ease;
    
            svg {
                width: 3rem;
                height: auto;
    
                path {
                    fill: gray; // Color de las estrellas no seleccionadas
                    transition: fill .3s ease; // Transición suave del color
                }
            }
    
            &:hover ~ .star svg path {
                fill: gold; // Color de las estrellas seleccionadas al hacer hover
            }
    
            &:hover svg path {
                fill: gold; // Color de la estrella seleccionada al hacer hover
            }
    
            &.selected ~ .star svg path {
                fill: gold; // Color de las estrellas seleccionadas al hacer hover
            }
     
            &selected svg path {
                fill: gold; // Color de la estrella seleccionada al hacer hover
            }
        }
    }
    
    .star:hover svg path,
    .star:hover~.star svg path,
    .star.highlighted svg path {
        fill: $primario;
    }
      `,
      imports: [CommonModule],
    })
    export class StarRatingComponent implements OnInit {
      @Input() rating: number = 0;
      @Output() ratingChange: EventEmitter<number> = new EventEmitter<number>();
      starsArray: boolean[] = new Array(5);
    
      selectRating(i: number) {
        this.ratingChange.emit(5 - i);
      }
      constructor() {}
    
      ngOnInit() {}
    }
    

    Stackblitz Demo