skip to Main Content

im having some issues with my star rating on a webpage.
i have a foreach loop where product details and a star rating are displayed for each product in my list.
However, now i am having the following issues:

  1. when i first select the stars on the first product, all is good
  2. when i click on the stars for the next product, it affects the rating for the first one

any help would be good!

This is part of the html

@foreach (var purchase in purchaseHistories)
                    {
                                        <div class="card rounded-3 mb-4">
                                          <div class="card-body p-4">
                                            <div class="row d-flex justify-content-between align-items-center">
                                              <div class="col-md-2 col-lg-2 col-xl-2">
                                                <img src="@purchase.ImageUrl" alt="@purchase.Name" class="img-fluid rounded-3" >
                                              </div>
                                              
                                              
                                              <div class="col-md-3 col-lg-3 col-xl-3">
                                                        <p class="lead fw-normal mb-2">@purchase.Name</p>
                                                        <p><span class="text-muted">@purchase.Description</span></p>
                                                        <p><span class="text-muted">Purchased On: @purchase.PurchaseDate</span></p>
                                                        <p><span class="text-muted">Quantity: @purchase.Quantity</span></p>
                                                        <button type="button" class="btn btn-primary">Download</button>
                                              </div>
                                              
                                              

                                        <div class="col-md-3 col-lg-3 col-xl-2 d-flex flex-column">

                                            <div class="star-rating-container"  >
                                                <label for="star">Review:</label>
                                                <div>
                                                <button class="star" type="button">☆</button>
                                                <button class="star" type="button">☆</button>
                                                <button class="star" type="button">☆</button>
                                                <button class="star" type="button">☆</button>
                                                <button class="star" type="button">☆</button>
                                                </div>
                                                
                                            </div>
                                        
                                        






                                                <label for="Activation Code">Activation Code: </label>
                                                <select class="form-select" aria-label="Activation Code">

                                                @{
                                                    var split = purchase.ActivationCode.Split(",");
                                                    var val = 0;
                                                }
                                                
                                                @for (int i = 0; i < split.Length; i++)
                                                {
                                                    if (i == 0)
                                                    {
                                                        <option selected>@split[i]</option>
                                                    }
                                                    else
                                                    {
                                                        val += 1;
                                                        <option value="@val">@split[i]</option>
                                                    }

                                                }
                                            </select>
                                        

                                    </div>

this is part of the javascript

const products=document.querySelectorAll('.product')



    const allstars = document.querySelectorAll('.star');
allstars.forEach((star, i) => {
    star.onclick = function () {
        let currentstar = i + 1;
        console.log(currentstar);

        allstars.forEach((star, j) => {
            if (currentstar >= j + 1) {
                star.innerHTML = '&#9733';
            } else {
                star.innerHTML = '&#9734';
            }
        })

    }
})

i tried adding another class to the star rating container but it doesnt seem to work..i dont know how to adjust this so that the id for each star rating container for each purchase can be individually contained

2

Answers


  1. This type of elements do not require JS at all these days. Everything can be done with modern CSS and old good radios. Collect the radios in one flex-direction: row-reverse container with those radios aligned in reverse order, add a decoration element if needed and rely on some sort of a input:checked ~ .deco selector.
    Here’s a codepen example:
    https://codepen.io/JaredSpb/pen/VwEjRoP

    But lets fix your code aswell. With a click you dont need to loop over all the stars at the page. Just loop over previous elements:

    
    star.onclick = function () {
    
        let prev = this;
        while( prev ){
            prev.innerHTML = '&#9733;';
            prev = prev.previousElementSibling;
        }
    
        // Also need to reset all the following
        let next = this.nextElementSibling;
        while( next ){
            next.innerHTML = '&#9734;';
            next = next.previousElementSibling;
        }
    
    }
    
    
    Login or Signup to reply.
  2. You need to define class .stars as a parent of .star and loop over the .stars to get the rating function works.

    const allstars = document.querySelectorAll('.stars');
    allstars.forEach((stars) => {
      [...stars.children].forEach((star, i) => {
        star.onclick = function () {
          let currentstar = i + 1;
          [...stars.children].forEach((star, j) => {
              if (currentstar >= j + 1) {
                  star.innerHTML = '&#9733;';
              } else {
                  star.innerHTML = '&#9734;';
              }
          })
        }
      });
    });
    <div class="star-rating-container">
        <label for="star">Review 1:</label>
        <div class="stars">
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
        </div>
    </div>
    <div class="star-rating-container">
        <label for="star">Review 2:</label>
        <div class="stars">
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
        </div>
    </div>
    <div class="star-rating-container">
        <label for="star">Review 3:</label>
        <div class="stars">
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
          <button class="star" type="button">&#9734;</button>
        </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search