Estoy trabajando en un proyecto con Symfony 4. Quiero implementar un sistema de clasificación por estrellas. Muestro 5 estrellas en cada fila en una tabla. Tengo dos problemas, uno es más importante que el otro.
Entonces, el primer problema es que quiero poder recuperar el valor de la estrella que seleccioné. Si selecciono 5 estrellas, quiero recuperar ese valor en mi controlador de entidad.
El segundo problema es que, actualmente, digamos que tengo 5 elementos en mi tabla, es decir, 5 filas. Actualmente, si selecciono 5 estrellas en una fila, se selecciona para todas las filas y ya no puedo seleccionar otro valor. Entonces, es global o algo así.
Aquí está el javascript que estoy usando:
<script> const stars = document.querySelectorAll('.star'); let check = false; stars.forEach(star => { star.addEventListener('mouseover', selectStars); star.addEventListener('mouseleave', unselectStars); star.addEventListener('click', activeSelect); }) function selectStars(e) { const data = e.target; const etoiles = priviousSiblings(data); if (!check) { etoiles.forEach(etoile => { etoile.classList.add('hover'); }) } } function unselectStars(e) { const data = e.target; const etoiles = priviousSiblings(data); if (!check) { etoiles.forEach(etoile => { etoile.classList.remove('hover'); }) } } function activeSelect(e) { if (!check) { check = true; document.querySelector('.note').innerHTML = 'Note ' + e.target.dataset.note; } } function priviousSiblings(data) { let values = [data]; while (data === data.previousSibling) { if (data.nodeName === 'I') { values.push(data); } } return values; } </script>Y aquí está el twig.html que estoy mostrando:
<td> <i class="star" data-note="1">★</i> <i class="star" data-note="2">★</i> <i class="star" data-note="3">★</i> <i class="star" data-note="4">★</i> <i class="star" data-note="5">★</i> <i class="note">Note:</i> </td>Quiero poder recuperar el valor una vez que hice una selección y tener una selección diferente para cada fila que tengo.
El problema está en los controladores de eventos "mouseover" y "mouseleave": selectStars y unselectStars . En "selectStars", está agregando la clase a una sola estrella. Y en "unselectStars", no estaba reiniciando ni aplicando el método de clase "eliminar" a otras estrellas.
De todos modos, así es como he logrado lo que estás tratando de hacer:
const ratings = document.querySelectorAll('.rating'); ratings.forEach(rating => rating.addEventListener('mouseleave', ratingHandler) ); const stars = document.querySelectorAll('.rating .star'); stars.forEach(star => { star.addEventListener('mouseover', starSelection); star.addEventListener('mouseleave', starSelection); star.addEventListener('click', activeSelect); }); function ratingHandler(e) { const childStars = e.target.children; for(let i = 0; i < childStars.length; i++) { const star = childStars.item(i) if (star.dataset.checked === "true") { star.classList.add('hover'); } else { star.classList.remove('hover'); } } } function starSelection(e) { const parent = e.target.parentElement const childStars = parent.children; const dataset = e.target.dataset; const note = +dataset.note; // Convert note (string) to note (number) for (let i = 0; i < childStars.length; i++) { const star = childStars.item(i) if (+star.dataset.note > note) { star.classList.remove('hover'); } else { star.classList.add('hover'); } } } function activeSelect(e) { const parent = e.target.parentElement const childStars = parent.children; const dataset = e.target.dataset; const note = +dataset.note; // Convert note (string) to note (number) for (let i = 0; i < childStars.length; i++) { const star = childStars.item(i) if (+star.dataset.note > note) { star.classList.remove('hover'); star.dataset.checked = "false"; } else { star.classList.add('hover'); star.dataset.checked = "true"; } } const noteTextElement = parent.parentElement.lastElementChild.children.item(0) noteTextElement.innerText = `Note: ${note}`; } Puede notar que tengo un componente de clase .rating . Este es un div que he creado para contener todas estas "estrellas". Aquí hay un enlace a un codepen que he creado. Siéntete libre de jugar con él.
Y como nota, proporcione demostraciones de codepen (o cualquier otro) para que podamos depurar un poco mejor y más rápido.
Espero que el enlace codepen te ayude a resolver tu problema.