Скрипт 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>