Stars rated selection in an Angular Project

41 Views Asked by At

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.

1

There are 1 best solutions below

0
Naren Murali On BEST ANSWER
  • We can use ngClass and add a class selected based on the selection made by the user!
  • We can use @Input and @Output to update the selected value of the user in the property called rating
  • We can use a logic where we emit 5 - then latest value since we are showing the stars reversed.

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