Несколько таймеров javascript на одной странице со сгенерированным списком Thymeleaf

Я борюсь с реализацией несколько раз на одной странице.

Я сделал простой скрипт, отсчитывающий время до определенной даты, которая отличается для каждого div. Все это работает отлично и денди на одном div, но не работает на других.

Содержимое, в котором оно отображается, представляет собой загрузочную карточку. Я не знаю, сколько карточек будет на странице, так как они приходят в виде списка, поэтому я не могу жестко закодировать это.

<div class = "row">
<div th:each = " transport : ${transports}">
    <div class = "card ml-1 mr-1 mt-3 mb-3 text-center text-primary">
        <figure>
            <div class = "card-body">
                <h6 class = "card-text"><small class = "text-dark font-italic">Time till departure</small></h6>
                <p  class = "timer"><small class = "text-muted" id = "timer">Time till departure</small></p>
            </div>
        </figure>
    </div>
</div>

Я знаю, что проблема заключается в id, но как мне динамически изменить id, чтобы он был уникальным для каждой карты?

Я использую Thymeleaf для создания шаблона.

Я пытался найти document.getElementsClassName("timer), но он не работает.

Я новичок в javascript, поэтому я думаю, что для этого есть наилучшая практика, но я не нашел ответа.

Спасибо за все советы.

<p  class = "timer">
<small class = "text-muted" id = "timer">
Time till departure
</small></p>
    <script th:inline = "javascript">
        const countDownDate = new Date(/*[[${transport.departureDate}]]*/).getTime();

          const x = setInterval(function () {

          const now = new Date().getTime();

          const distance = countDownDate - now;

          onst days = Math.floor(distance / (1000 * 60 * 60 * 24));
          onst hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
          const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
          const seconds = Math.floor((distance % (1000 * 60)) / 1000);

          document.getElementById("timer").innerHTML = days + "d " + hours + "h "
                            + minutes + "m " + seconds + "s ";

          if (distance < 0) {
             clearInterval(x);
             document.getElementById("timer").innerHTML = "EXPIRED";
             }
               }, 1000);
    </script>

Привет, как вы получаете эту карту и как вы вставляете эту карту в DOM?

lissettdm 12.12.2020 18:16

@lissettdm Я обновил код. Это список <Transport> transportList. В классе «Транспорт» есть поле «Дата отправления». Он должен показывать индивидуальный таймер для каждого экземпляра класса.

kryzystof 12.12.2020 18:29

этот document.getElementsClassName("timer") возвращает список узлов, который очень похож на массив, поэтому этот document.getElementsClassName("timer")[0] захватит первый элемент в этом списке узлов

KienHT 12.12.2020 18:33

Чтобы создать уникальный идентификатор, вы можете использовать Date.now(), это возвращает количество миллисекунд с 1 января 1970 года по настоящее время.

KienHT 12.12.2020 18:36

Вы можете использовать iterStat, чтобы получить индекс и создать уникальный идентификатор для каждой карты. Вы говорите, что каждая карта имеет разное время, это время является частью транспортного объекта, где вы храните информацию о времени?

lissettdm 12.12.2020 18:42

@lissettdm, не могли бы вы уточнить? Я совершенно новичок в JS.

kryzystof 12.12.2020 18:48

@KienHT вы имеете в виду document.getElementsByClassName("timer")[0].innerHTML? Потому что это не работает. Я новичок в JS, поэтому, возможно, я неправильно его реализую.

kryzystof 12.12.2020 18:50

Конечно, я обновил свой ответ.

lissettdm 12.12.2020 18:58
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
8
311
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Попробуйте со статусом итерации. Таким образом вы можете получить значение индекса и определить уникальное имя класса для каждого элемента:

    <div th:each = " transport, iterStat : ${transports}">
        <div class = "card ml-1 mr-1 mt-3 mb-3 text-center text-primary">
            <figure>
                <div class = "card-body">
                    <h6 class = "card-text"><small class = "text-dark font-italic">Time till departure</small></h6>
                    <p  th:id = "'timer-' + ${iterStat.index}"><small class = "text-muted" id = "timer">Time till departure</small></p>
                    <script th:inline = "javascript">
                        //...
                        const index=/*[[${iterStat.index}]]*/
                        document.getElementById(`timer-${index}').innerHTML = days + "d " + hours + "h "
                            + minutes + "m " + seconds + "s ";

                         //..
                    </script>
                </div>
            </figure>
        </div>
    </div>

Большое спасибо за ответ, но, к сожалению, я получаю исключение Не удалось разобрать как выражение: "'timer-'${iterStat.index}" (шаблон: "choose_transport" - строка 103, столбец 25) и должно ли это быть <p th:class = "'timer-'${iterStat.index}"> или <p th:id = "'timer-'${iterStat.index}">, поскольку document.getElementById ссылается на идентификатор

kryzystof 12.12.2020 20:08

Извините, да должно быть (th:id = "'timer-' + ${iterStat.index}"). Я пропустил +. Я обновил свой ответ.

lissettdm 12.12.2020 20:45

Таймер работает только с последним <div>. Столько времени на это потратил. Нужно перейти к другой задаче. Спасибо за ваше время, сэр.

kryzystof 13.12.2020 01:12
Ответ принят как подходящий

Решено с помощью решения @lissetrdm, но все значения должны быть в функции.

<div th:each = " transport, iterStat : ${transports}">
<p  class = "card-text" th:id = "'timer-' + ${iterStat.index}"><small class = "text-muted" id = "timer">Time till departure</small></p>


<script th:inline = "javascript">




    var x = setInterval(function () {
        var countDownDate = new Date(/*[[${transport.departureDate}]]*/).getTime();
        var index = [[${iterStat.index}]];

        console.info(index);

        var now = new Date().getTime();

        var distance = countDownDate - now;

        var days = Math.floor(distance / (1000 * 60 * 60 * 24));
        var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
        var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
        var seconds = Math.floor((distance % (1000 * 60)) / 1000);

        document.getElementById('timer-'+index).innerHTML = days + "d " + hours + "h "
            + minutes + "m " + seconds + "s ";
        if (distance < 0) {
            clearInterval(x);
            document.getElementById('timer-'+index).innerHTML = "EXPIRED";
        }
    }, 1000);
</script>

Другие вопросы по теме