title: How to make dynamic star rating with JSON data
body: <p>I am working on a star rating system for when you visit any restaurant, all the `Attributes' I have to show on UI are dynamic for which I am getting data in JSON format</p>
  
  <p>Here I have five attributes each of them having up to 5 star rating option</p>
  
  <p>My data:</p>
  
  <pre><code>    [
            {
              "ATTRIBUTEID": "FOODQUALITY",
              "ATTRIBUTENAME": "Quality Of Food",
              "POSITION": 1
            },
            {
              "ATTRIBUTEID": "CLEANLINESS",
              "ATTRIBUTENAME": "Cleanliness",
              "POSITION": 2
            },
            {
              "ATTRIBUTEID": "SERVICE",
              "ATTRIBUTENAME": "Service",
              "POSITION": 3
            },
            {
              "ATTRIBUTEID": "STAFFBEHAVE",
              "ATTRIBUTENAME": "Staf Behavior",
              "POSITION": 4
            },
            {
              "ATTRIBUTEID": "AMBIENCE",
              "ATTRIBUTENAME": "Ambience",
              "POSITION": 5
            }
          ];
  </code></pre>
  
  <p>What I am trying to achieve is this:</p>
  
  <p><a href="https://i.stack.imgur.com/ZcFA7.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ZcFA7.jpg" alt="Image"></a></p>
  
  <p><strong>What I have done</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="true" data-console="true" data-babel="false">
  <div class="snippet-code snippet-currently-hidden">
  <pre class="snippet-code-css lang-css prettyprint-override"><code>@charset "ISO-8859-1";
  div.stars {
    width: 300px;
    display: inline-block;
    margin-left: -35px;
  }
  
  .commonLable {
    margin-left: 55px;
    font-family: sans-serif;
    font-weight: bold;
    margin-bottom: 0;
  }
  
  input.star {
    display: none;
  }
  
  label.star {
    float: right;
    padding: 5px;
    font-size: 40px;
    color: grey;
    transition: all .2s;
    margin-top: -25px;
  }
  
  hr {
    margin: 0;
  }
  
  input.star:checked~label.star:before {
    content: '\2605';
    color: #ffd309;
    transition: all .25s;
  }
  
  input.star-5:checked~label.star:before {
    color: #ffe840;
    text-shadow: 0 0 20px #952;
  }
  
  input.star-1:checked~label.star:before {
    color: #f24800;
  }
  
  label.star:hover {
    transform: rotate(-15deg) scale(1.3);
    cursor: pointer;
  }
  
  label.star:before {
    content: '\2605';
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;
  &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"&gt;
  &lt;link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"&gt;
  &lt;script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"&gt;&lt;/script&gt;
  &lt;div class="stars"&gt;
    &lt;form action=""&gt;
  
      &lt;div class="form-row"&gt;
        &lt;label class="commonLable"&gt; Cleanliness&lt;/label&gt;
        &lt;div class="form-group col-lg-12"&gt;
          &lt;input class="star star-5" id="star-5" type="radio" name="star" value="5" /&gt;
          &lt;label class="star star-5" for="star-5"&gt;&lt;/label&gt;
          &lt;input class="star star-4" id="star-4" type="radio" name="star" value="4" /&gt;
          &lt;label class="star star-4" for="star-4"&gt;&lt;/label&gt;
          &lt;input class="star star-3" id="star-3" type="radio" name="star" value="3" /&gt;
          &lt;label class="star star-3" for="star-3"&gt;&lt;/label&gt;
          &lt;input class="star star-2" id="star-2" type="radio" name="star" value="2" /&gt;
          &lt;label class="star star-2" for="star-2"&gt;&lt;/label&gt;
          &lt;input class="star star-1" id="star-1" type="radio" name="star" value="1" /&gt;
          &lt;label class="star star-1" for="star-1"&gt;&lt;/label&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="form-row"&gt;
        &lt;label class="commonLable"&gt; Quality Of Food
  &lt;/label&gt;
        &lt;div class="form-group col-lg-12"&gt;
          &lt;input class="star star-5" id="star-5r" type="radio" name="starr" /&gt;
          &lt;label class="star star-5" for="star-5r"&gt;&lt;/label&gt;
          &lt;input class="star star-4" id="star-4r" type="radio" name="starr" /&gt;
          &lt;label class="star star-4" for="star-4r"&gt;&lt;/label&gt;
          &lt;input class="star star-3" id="star-3r" type="radio" name="starr" /&gt;
          &lt;label class="star star-3" for="star-3r"&gt;&lt;/label&gt;
          &lt;input class="star star-2" id="star-2r" type="radio" name="starr" /&gt;
          &lt;label class="star star-2" for="star-2r"&gt;&lt;/label&gt;
          &lt;input class="star star-1" id="star-1r" type="radio" name="starr" /&gt;
          &lt;label class="star star-1" for="star-1r"&gt;&lt;/label&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/form&gt;
  &lt;/div&gt;
  &lt;/form&gt;
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>at the end of the form there will be a submit button which will send action to server to save the feedback, as I am lacking in approach I think, like how it will work and how should I do it.</p>
  
  <h2>Edit</h2>
  
  <p>I have edited my snippet where I have two attributes <code>Quality of food</code>, <code>Cleanliness</code> but when I click on <code>Cleanliness</code> stars the above star gets colored filled, I know that is because of common css, but that is my issue All the attributes are dynamic, please check my JSON data I have uploaded Image of what I am trying to do.</p>
  
  <h2>Edit</h2>
  
  <p>This is dynamic code which is creating stars and labels dynamically</p>
  
  <p><div class="snippet" data-lang="js" data-hide="true" data-console="true" data-babel="false">
  <div class="snippet-code snippet-currently-hidden">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>$(document).ready(function() {
    var data = [{
        "ATTRIBUTEID": "FOODQUALITY",
        "ATTRIBUTENAME": "Quality Of Food",
        "POSITION": 1
      },
      {
        "ATTRIBUTEID": "CLEANLINESS",
        "ATTRIBUTENAME": "Cleanliness",
        "POSITION": 2
      },
      {
        "ATTRIBUTEID": "SERVICE",
        "ATTRIBUTENAME": "Service",
        "POSITION": 3
      },
      {
        "ATTRIBUTEID": "STAFFBEHAVE",
        "ATTRIBUTENAME": "Staf Behavior",
        "POSITION": 4
      },
      {
        "ATTRIBUTEID": "AMBIENCE",
        "ATTRIBUTENAME": "Ambience",
        "POSITION": 5
      }
    ];
  
    for (v = 0; v &lt; data.length; v++) {
  
      var container = document.getElementById("container");
  
      var firstDiv = document.createElement('div');
      firstDiv.setAttribute("class", "form-row");
  
      var secondDiv = document.createElement('div');
      secondDiv.setAttribute("class", "commonLable");
      secondDiv.append(data[v].ATTRIBUTENAME);
  
  
      var thirdDiv = document.createElement('div');
      thirdDiv.setAttribute("class", "form-group col-lg-12");
  
      /// append stars 
  
      for (i = 1; i &lt; data.length + 1; i++) {
        var incrementedVar = i + 1;
        var stars = document.createElement("input");
        var label = document.createElement("label");
        stars.setAttribute("type", "radio");
        stars.setAttribute("id", '"' + data[v].ATTRIBUTEID + i + '"');
        stars.setAttribute("name", '"' + data[v].ATTRIBUTEID + i + '"');
        stars.setAttribute("class", "star star-5");
        stars.setAttribute("value", i);
        label.setAttribute("class", "star star-5");
        label.setAttribute("for", '"' + data[v].ATTRIBUTEID + i + '"');
        thirdDiv.append(stars, label);
  
      }
  
      secondDiv.append(thirdDiv);
      firstDiv.append(secondDiv);
      container.appendChild(firstDiv);
    }
    $('input:radio').change(
      function() {
  
        alert($(this).val());
      });
  });</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>@charset "ISO-8859-1";
  div.stars {
    width: 300px;
    display: inline-block;
    margin-left: -35px;
  }
  
  .commonLable {
    margin-left: 55px;
    font-family: sans-serif;
    font-weight: bold;
    margin-bottom: 0;
  }
  
  input.star {
    display: none;
  }
  
  label.star {
    float: right;
    padding: 5px;
    font-size: 40px;
    color: grey;
    transition: all .2s;
    margin-top: -25px;
  }
  
  hr {
    margin: 0;
  }
  
  input.star:checked~label.star:before {
    content: '\2605';
    color: #ffd309;
    transition: all .25s;
  }
  
  input.star-5:checked~label.star:before {
    color: #ffe840;
    text-shadow: 0 0 20px #952;
  }
  
  input.star-1:checked~label.star:before {
    color: #f24800;
  }
  
  label.star:hover {
    transform: rotate(-15deg) scale(1.3);
    cursor: pointer;
  }
  
  label.star:before {
    content: '\2605';
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"&gt;&lt;/script&gt;
  &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"&gt;
  &lt;link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"&gt;
  &lt;div class="stars"&gt;
    &lt;form action="" id="container"&gt;
  
    &lt;/form&gt;
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>In the second snippet I have added the dynamic code which is not taking css correctly.</p>
  
  <p>Issue: once if I had marked the stars and want to unmarked them from 4 to 2 it is not happening. Please check snippet 1 where I have static code using HTML, I want that type of functionality.</p>