Javascript для нескольких элементов в цикле PHP

Я создал таблицу HTML, в которой каждая строка извлекает данные из таблицы базы данных sql.

?>
<div class = "container">
    <h2>Activities</h2>
    <table class = "table table-striped">
    <thead>
        <tr>
        <th scope = "col">#</th>
        <th scope = "col">Date</th>
        <th scope = "col">Position</th>
        <th scope = "col">Activity Type</th>
        <th scope = "col">Edit</th>
        </tr>
    </thead>
    <tbody>
        <?php
        $incremental=0;
        while($selRow=$res_selPostData->fetch_assoc()) {
            $incremental +=1;
            $filepath='.\outputs\\' . 'verbale' . $selRow['IDIntervento'] . '.pdf'; 
        ?>
            <tr>
                <td><?php echo $selRow['IDActivity']; ?></td>
                <td><?php echo $selRow['DateActivity']; ?></td>
                <td><?php echo $selRow['Position']; ?></td>
                <td><div id=<?php echo "TypeAct" . $incremental; ?>><?php echo $selRow['Activity_type']; ?></div></td>
                <td><div id=<?php echo "button" . $incremental; ?>><span id='edit'>EDIT</span></div></td>
            </tr>

        <?php
        }
        ?>
    </tbody>
    </table>
</div>

Последний столбец таблицы HTML содержит для каждой строки «кнопку», которая связана со следующей функцией javascript.

<script>
    window.onload = function() {
                var maximum=parseInt(<?php echo $incremental; ?>);
                for (let i = 1; i<maximum; i++) {
                    var makeMod = document.getElementById('TypeAct' + 'i');
                    var div = document.getElementById('button' + 'i');
                    div.onclick = function(e) {
                        makeMod.contentEditable = true;
                        makeMod.focus();
                        makeMod.style.backgroundColor = '#E0E0E0';
                        makeMod.style.border = '1px dotted black';
                    }
                }
            }
</script>

Я пытался использовать скрипт без цикла for с

<td><div id=<?php echo "button"; ?>><span id='edit'>EDIT</span></div></td>

и

var makeMod = document.getElementById('TypeAct')` and `var div = document.getElementById('button')

но в этом случае функция работает только для одной строки.

Изменение «i» на «i» решило проблему с «кнопкой», но когда я нажимаю кнопку в разных строках, редактируемым становится только тип активности в последней строке, а не тот, который находится в той же строке, что и кнопка; как если бы функция воздействовала только на последнюю сгенерированную строку в цикле while таблицы. Можете ли вы догадаться, почему?

как должно работать, когда вы получаете элемент и объединяете строку «i», а не значение вашей переменной ivar makeMod = document.getElementById('TypeAct' + 'i');, вы должны изменить ее на это var makeMod = document.getElementById('TypeAct' + i);

Chris G 19.04.2023 21:50

Это решило проблему с «кнопкой», но когда я нажимаю кнопку в разных строках, редактируемым становится только тип активности в последней строке, а не тот, который находится в той же строке, что и кнопка; как если бы функция воздействовала только на последнюю сгенерированную строку в цикле while таблицы. Можете ли вы догадаться, почему?

Federico 19.04.2023 22:06

еще одна проблема: идентификаторы уникальны, и эта часть вашего кода находится внутри цикла, у вас не может быть нескольких элементов с одним и тем же идентификатором, поэтому измените его, как вы сделали с другими идентификаторами <span id='edit'>EDIT</span>

Chris G 19.04.2023 22:33

Это действительно проблема PHP? Почему бы сначала не сгенерировать статическую разметку, запустить ее со всей этой логикой JS, а затем динамически построить разметку?

Nico Haase 20.04.2023 09:34
Поведение ключевого слова "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) для оценки ваших знаний,...
0
4
67
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

В этой строке:

var div = document.getElementById('button' + 'i');

«i» находится в кавычках, таким образом, получается не расчетное значение, а буквально буква «i». Вместо этого попробуйте:

var div = document.getElementById('button' + i);

и в идеале используйте дефис между кнопкой слова и переменной приращения, например:

id = "button-1" id = "button-2" etc.
Ответ принят как подходящий

Я использую образец HTML с образцами данных, которые я сделал только для проверки кода, так как здесь нельзя воспроизвести PHP.

  1. Первым делом замените строку i на переменную (что вы уже сделали)

    makeMod = document.getElementById('TypeAct-' + i);

  2. Эта строка кода находится внутри цикла. <span id='edit'>EDIT</span>, что означает, что у вас будет несколько элементов с идентификатором edit. Этого не может быть, поэтому измените его, как вы сделали с другими идентификаторами. Вы можете объединить свою переменную php $incremental, как и с другими.

  3. Измените свой цикл на этот for (let i = 1; i <= maximum; i++) {, если вы оставите его на i < maximum, тогда он не добавит событие к вашей последней кнопке.

  4. Теперь гораздо лучше использовать let и const вместо var. Подробнее здесь

  5. Используйте addEventListener вместо onclick. Почему? подробнее об этом читайте здесь addEventListener-vs-onclick

window.onload = function() {
  let maximum = 3;//sample value, leave this line like in your original code
  let makeMod;
  for (let i = 1; i <= maximum; i++) {
    document.getElementById('button-' + i).addEventListener("click", function(e) {
      makeMod = document.getElementById('TypeAct-' + i);
      makeMod.contentEditable = true;
      makeMod.focus();
      makeMod.style.backgroundColor = '#E0E0E0';
      makeMod.style.border = '1px dotted black';
    });
  }
}
<div class = "container">
  <h2>Activities</h2>
  <table class = "table table-striped">
    <thead>
      <tr>
        <th scope = "col">#</th>
        <th scope = "col">Date</th>
        <th scope = "col">Position</th>
        <th scope = "col">Activity Type</th>
        <th scope = "col">Edit</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>some data</td>
        <td>some data</td>
        <td>some data</td>
        <td>
          <div id = "TypeAct-1">act 1</div>
        </td>
        <td>
          <div id = "button-1"><span id='edit-1'>EDIT</span></div>
        </td>
      </tr>
      <tr>
        <td>some data</td>
        <td>some data</td>
        <td>some data</td>
        <td>
          <div id = "TypeAct-2">act 2</div>
        </td>
        <td>
          <div id = "button-2"><span id='edit-2'>EDIT</span></div>
        </td>
      </tr>
      <tr>
        <td>some data</td>
        <td>some data</td>
        <td>some data</td>
        <td>
          <div id = "TypeAct-3">act 3</div>
        </td>
        <td>
          <div id = "button-3"><span id='edit-3'>EDIT</span></div>
        </td>
      </tr>
    </tbody>
  </table>
</div>

Это решило проблему полностью! Большое спасибо

Federico 19.04.2023 23:08

рад, что это помогло, пожалуйста, примите ответ и проголосуйте за него, это также приветствуется :)

Chris G 19.04.2023 23:20

Было бы лучше, IMO, полностью удалить атрибуты ID, если вам нужно использовать числовой суффикс, чтобы помочь идентифицировать элементы, и полагаться на другие, более гибкие средства идентификации элементов DOM, такие как querySelector, querySelectorAll и другие родитель/потомок/брат. введите свойства и методы. В приведенном выше примере единственное использование, которое имеет переменная PHP $incremental, — это числовой суффикс — он не будет играть никакой роли в какой-либо фактической операции edit (отправка формы / ajax и т. д.), когда запись должна быть отредактирована, поэтому ее можно удалить. Таблица создается с содержимым из базы данных, поэтому у вас есть IDActivity, который будет полезен в операции редактирования, поэтому назначьте его как значение идентификатора данных!

Идентификация событий click может быть выполнена с помощью delegated event listener вместо того, чтобы назначать прослушиватель событий каждому button.

Я также добавил обработчик событий blur к элементам DIV contentEditable, который возвращает их в нормальное состояние, когда они больше не используются. Этот обработчик blur можно использовать для отправки ajax-запроса на редактирование записи в БД.

const d=document;
const CN='editable';

d.querySelector('.container table').addEventListener('click', e=>{
  if ( e.target instanceof HTMLSpanElement && e.target.dataset.type == 'edit' ) {
    let id=e.target.parentNode.dataset.id;
    let content = e.target.parentNode.closest('tr').querySelector('div[data-type = "content"]');
        content.contentEditable=true;
        content.focus();
        content.classList.add( CN );
        
    console.info( ' -> Id=%s',id )
  }
});

d.querySelectorAll('[data-type = "content"]').forEach(n=>n.addEventListener('blur',e=>{
  if ( e.target.classList.contains( CN ) ){
    e.target.classList.remove( CN );
    e.target.contentEditable=false;
    
    // update using ajax?
    console.info(e.target.dataset.id,e.target.textContent);
  }
}));
.editable{
  background:#E0E0E0;
  border:1px dotted black
}
<div class = "container">
  <h2>Activities</h2>
  <table class = "table table-striped">
    <thead>
      <tr>
        <th scope = "col">#</th>
        <th scope = "col">Date</th>
        <th scope = "col">Position</th>
        <th scope = "col">Activity Type</th>
        <th scope = "col">Edit</th>
      </tr>
    </thead>
    <tbody>
      <!-- emulated content -->
      <!--
        The `IDActivity` value is what would be assigned
        to the `data-id` attribute below. That `data-id`
        is easily accessible in Javascript and can be used
        for whatever EDIT operation you wish.
        
        ie: 
        <td>
          <div data-id = "<?=$selRow['IDActivity'];?>">
            <?=$selRow['Activity_type'];?>
          </div>
        </td>
      -->
      <tr>
        <td>1</td>
        <td>2023/04/15</td>
        <td>Midfield</td>
        <td><div data-id=1 data-type='content'>Banana Bouncing</div></td>
        <td><div data-id=1><span data-type='edit'>EDIT</span></div></td>
      </tr>
      <tr>
        <td>2</td>
        <td>2023/04/17</td>
        <td>Ground-Level</td>
        <td><div data-id=2 data-type='content'>Hedgehog Juggling</div></td>
        <td><div data-id=2><span data-type='edit'>EDIT</span></div></td>
      </tr>
      <tr>
        <td>3</td>
        <td>2023/04/18</td>
        <td>Upstairs</td>
        <td><div data-id=3 data-type='content'>Dwarf Tossing</div></td>
        <td><div data-id=3><span data-type='edit'>EDIT</span></div></td>
      </tr>
      <!-- end emulated content -->
    </tbody>
  </table>
</div>

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