Скрипт JS не итерируется внтури цикла for в шаблоне Django

Всем привет! Проблема в следующем:

Я пишу проект интернет магазина на Django. Начал делать отправку товара в избранное по нажатию кнопки "Сердечко". С точки зрения Django все ок, но мне захотелось менять цвет у иконки сердечка, когда оно нажато и когда нет. Погуглил данный вопрос, он решается JS скриптом. Скрипт написал, он отлично работает, НО только на одной кнопке. В Django шаблоне у меня есть цикл который итерирует товары и выводит в шаблоне все необходимые сведения: цена, название и тд., в том числе и иконку сердечка для каждого товара. Я пытался предавать id "сердечка" в переменную в скрипт JS. Но итерация не работает для скрипта. То есть весь шаблон итерируется нормально, а скрипт выполняет свою работу только для первой иконки.

Вот код:


{% for product in products %}
<a id="{{product}}" class='black'></a>

                        <script>
                        let x = "{{product}}";
                        
                        let btn_x = document.getElementById(x);
                        let default_color = "black";
                        if (localStorage.getItem("default_color")!== null) {
                            default_color = localStorage.getItem("default_color")
                        } else {
                          localStorage.setItem("default_color",default_color)
                        };
                        btn_x.className = default_color;

                        btn_x.onclick = function () {
                          if (default_color === "black") {
                            btn_x.className = "red";
                            default_color = "red";
                            localStorage.setItem("default_color", default_color);
                          } else {
                            btn_x.className = "black";
                            default_color = "black";
                            localStorage.setItem("default_color", default_color);
                          }
                        };

                    </script>
{% endfor%}

Заранее спасибо.

Немного переписал код. Теперь делаю тоже самое но через цикл. Теперь проблема в том, что в localStorage сохраняется значение по ключу который относиться к последней кнопке в цикле. То есть, какую бы иконку я не кликал, цвет меняется только у последней иконки. Видимо я где-то что-то не то делаю в цикле или надо что-то вынести вне цикла, но я не понимаю что.

Вот исправленный код:

{% for product in products %}
<a data-num='{{product}}'class='heart2'></a>
{% endfor %}
<script>

const hearts = [...document.querySelectorAll('.heart2')];

            for (i in hearts) {
              heart = hearts[i];
              console.log(heart);
              current_class = "heart2";
              if (localStorage.getItem(i)) {
                  current_class = localStorage.getItem(i);
                } else {
                  current_class = "heart2";
                  localStorage.setItem(i,current_class);
                }
              heart.className = current_class;

              heart.addEventListener('click',
              function(){
                  if(current_class == "heart2"){
                    heart.className = "heart_checked";
                    localStorage.setItem(i,"heart_checked");
                    current_class = "heart_checked";
                  } else{
                    heart.className = "heart2";
                    localStorage.setItem(i,"heart2");
                    current_class = "heart2";
                  }
              });
            }

</script>


В итоге решил вот так:

{% for product in products %}
  <a id="{{product}}" name='button'class='heart2'></a>
{% endfor %}

<script>
            let hearts = document.querySelectorAll('a[name^="button"]');

            for (let heart of hearts) {
              if (localStorage.getItem(heart.id)) {
                  default_class = localStorage.getItem(heart.id)
                } else {
                  default_class = "heart2"
                  localStorage.setItem(heart.id,default_class)
                }
              heart.className = default_class;

              heart.addEventListener('click',function(){
                if (event.target.className == 'heart2'){
                  event.target.className = 'heart_checked'
                  localStorage.setItem(event.target.id, 'heart_checked')
                }else{
                  event.target.className ='heart2'
                  localStorage.setItem(event.target.id, 'heart2')
                }
                console.log(localStorage);
              })}

</script>

До этого с JS не сталкивался, это жесть конечно, одних только вариантов обойти элементы в цикле 4 штуки накопал пока искал решение...

В итоге на одном из форумов подсказали, что так делать можно, но подход неправильный.

Храня данные о классе кнопки в LocalStorage я по факту потеряю состояние кнопки при заходе с нового браузера. Правильное решение, хранить состояние кнопки в моделях Django, точнее не состояние кнопки, а проверять есть ли товар в избранном или нет, и в соответствии с его статусом уже менять класс кнопки в JS скрипте. Код становиться в несколько раз короче и нет нужды дублировать в других шаблонах. Простыми словами, предыдущий код это костыль, да к тому же плохо работающий. Вот рабочее решение:

{% for product in products %}
  <a  name='heart_favorites' class="btn_favorites" href= 
     "{%url'products:favorites_add' product.article %}">
      <svg data-is_favorite="{{product.is_favorite}}"class="favorites_heart"> </svg>
  </a>
{% endfor %}

   <script>
    let hearts = document.querySelectorAll('a[name^="heart_favorites"]');
    
    for (let heart of hearts) {
    
      var heart_child_elem = heart.children[0];
      
      if (heart_child_elem.getAttribute('data-is_favorite') == 'True') {
          heart_child_elem.setAttribute('class','favorites_heart_checked');
        } else {
          heart_child_elem.setAttribute('class','favorites_heart');
        }
      };
  </script>

Вернуться на верх