Невозможно установить HTML для onchange для ввода

Я создаю входные данные в таблице через цикл. Сначала я создаю новую ячейку

var nestedCell = newRow.insertCell(columncounter);

Затем я создаю новый вход, каждый вход имеет уникальный идентификатор.

let input = document.createElement('input');
input.type = 'text';
input.id = thisInputID;
input.value = value;

Затем я пытаюсь вставить функцию «onchange» на этот вход.

input.onchange =  function() { 
   alert(thisInputID);
}

Функция onchange запускается, но поскольку значение thisInputID меняется на каждой итерации, вместо идентификатора для этого конкретного ввода отображается только последний «thisInputID». Это проблема. Как назначить функцию onchange для каждого ввода, которая будет передавать уникальный идентификатор для этого ввода?

Вот код в одном блоке:

                        var nestedCell = newRow.insertCell(columncounter);

                        let input = document.createElement('input');
                        input.type = 'text';
                        input.id = thisInputID;
                        input.value = value;
                        input.onchange =  function() { 
                            alert(thisInputID);
                        }

                        nestedCell.appendChild(input);

Обновлено: вы уже дали мне рабочий ответ :) но вот jsfiddle, показывающий проблему https://jsfiddle.net/carlschwarz/2bw1dm8k/1/

Вы разместили недостаточно кода, чтобы прояснить это, но объявление thisInputID, вероятно, является ключом к проблеме. Как и где это декларируется? Есть ли какая-то петля? Как это выглядит?

Pointy 20.08.2024 14:52

Переходим к делу: вам следует объявлять переменные с помощью let или const, а не var.

Pointy 20.08.2024 14:53

@Pointy Я предполагаю, что это «псевдо»-код, и ОП хочет получить фактический идентификатор ввода, который вызвал onchange

DarkBee 20.08.2024 14:54

@DarkBee нет, ОП явно использует что-то, что генерирует значения идентификаторов, а затем в коде, опубликованном в верхней части вопроса, сгенерированный идентификатор используется для создания нового элемента ввода.\

Pointy 20.08.2024 14:55

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

DarkBee 20.08.2024 14:59
Поведение ключевого слова "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
5
51
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Если ему просто нужно оповестить себя id, вы можете получить к нему прямой доступ:

input.onchange = function() { 
  alert(this.id);
}

переменные внутри циклов for, объявленные с помощью var, имеют область действия функции. Вы можете использовать объявления на уровне блока, const/let, слушать других, пока они указывают решение, или сделать эту уродливую вещь, которая захватывает переменную:

input.onchange =  ((id) => function() { 
  alert(id);
})(thisInputID)
  1. Пожалуйста, сгенерируйте действительный HTML
  2. Пожалуйста, используйте делегированные обработчики событий — ввод работает лучше, чем изменение.
  3. Пожалуйста, не используйте внутренний HTML, поскольку он уязвим для XSS.

https://jsfiddle.net/mplungjan/bv4hxgce/

const addData = (jsonInput, tablename, nestID) => {
  const jsonObject = JSON.parse(jsonInput);
  const table = document.querySelector(`#${tablename}`);

  // Ensure thead and tbody elements exist
  const thead = table.querySelector('thead') || table.appendChild(document.createElement('thead'));
  const tbody = table.querySelector('tbody') || table.appendChild(document.createElement('tbody'));

  // Create and populate header row in thead
  const headerRow = thead.insertRow(-1); // Insert row in thead
  const headers = Object.keys(jsonObject[0]);
  headers.forEach(header => {
    const cell = headerRow.insertCell();
    cell.innerText = header;
  });

  // Populate the data rows in tbody
  jsonObject.forEach((item, index) => {
    const dataRow = tbody.insertRow(-1);
    headers.forEach(header => {
      const cell = dataRow.insertCell();
      const input = document.createElement('input');
      input.type = 'text';
      input.value = item[header];
      input.id = `${nestID}[${index}].${header}`;
      cell.appendChild(input);
    });
  });

  // Event delegation for input onchange
  tbody.addEventListener('input', function(event) {
    const target = event.target;
    if (target.tagName === 'INPUT') {
      console.info(target.id); // Changed from alert to console.info for better UX in examples
    }
  });
};

let jsonInput = '[{"id":167915,"type":"variation","date_created":"2024-04-18T12:09:44"},{"id":167916,"type":"variation","date_created":"2024-04-18T12:09:44"},{"id":167917,"type":"variation","date_created":"2024-04-18T12:09:44"}]';
addData(jsonInput, "outputTable", "");
.as-console-wrapper { height: 60px; }
<table id = "outputTable"></table>

Вы можете назначить функцию обратного вызова события следующим образом:

input.onchange = onChange;

Например, вот как вы можете использовать event, чтобы получить информацию о входных данных:

function onChange(event) {
  const input = event.target;
  console.info(`UPDATE ${input.id} = ${input.value}`);
}

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

initSpreadsheet(document.getElementById('myTable'), 5, 5);

function initSpreadsheet(table, rows, columns) {
  let thead = table.getElementsByTagName('thead')[0];
  let tbody = table.getElementsByTagName('tbody')[0];

  if (!thead) table.append(thead = document.createElement('thead'));
  if (!tbody) table.append(tbody = document.createElement('tbody'));

  const headerRow = thead.insertRow(0);
  const topLeft = headerRow.insertCell(0);
  topLeft.outerHTML = '<th></th>';
  for (let c = 0; c < columns; c++) {
    const headerCell = headerRow.insertCell(c + 1);
    headerCell.outerHTML = `<th>${indexToColumn(c + 1)}</th>`;
  }

  for (let r = 0; r < rows; r++) {
    const currentRow = tbody.insertRow(r);
    const rowIdentifier = currentRow.insertCell(0);
    rowIdentifier.outerHTML = `<th>${r + 1}</th>`;
    for (let c = 0; c < columns; c++) {
      const cell = currentRow.insertCell(c + 1);
      const input = document.createElement('input');
      input.type = 'text';
      input.id = `${indexToColumn(c + 1)}${r + 1}`;
      input.onchange = onChange;
      cell.appendChild(input);
    }
  }
}

function onChange(event) {
  const input = event.target;
  console.info(`UPDATE ${input.id} = ${input.value}`);
}

function indexToColumn(index) {
  if (index <= 0) throw new Error("Index must be a positive integer.");
  index -= 1; // Adjust index for zero-based calculation
  const letter = String.fromCharCode(index % 26 + 'A'.charCodeAt(0));
  return index < 26 ? letter : indexToColumn(Math.floor(index / 26)) + letter
}
.as-console-wrapper {
  max-height: 3rem !important;
}

/* Spreadsheet layout */
.speadsheet {
  border-collapse: collapse;
}
.speadsheet,
.speadsheet th,
.speadsheet td,
.speadsheet input {
  box-sizing: border-box;
}
.speadsheet th {
  font-family: Arial;
  font-weight: normal;
  padding: 0.125rem 0.25rem;
}
.speadsheet td {
  padding: 0;
  margin: 0;
}
.speadsheet td input {
  width: 4rem;
  height: 100%;
  margin: 0;
  padding: 0.25rem;
  border: none;
}

/* Spreadsheet theme */
.speadsheet,
.speadsheet th,
.speadsheet td {
  border: thin solid #CCC;
}
.speadsheet th {
  background: #DDD;
}
.speadsheet tbody tr:nth-child(even) td {
  background: #EEE;
}
.speadsheet td input {
  background: transparent;
}
<table id = "myTable" class = "speadsheet"></table>

Кроме того, вы можете использовать this.id внутри onchange, я бы предложил аналогичный подход, который не использует недопустимые идентификаторы, использует правильные атрибуты name = "" и т. д.:

const el = (sel, par = document) => par.querySelector(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);

const addData = (jsonInput, tablename) => {
  const data = JSON.parse(jsonInput);
  const elTable = el(tablename);

  // THEAD
  const elThead = elNew("thead");
  const elTr = elNew("tr");
  const elsTh = Object.keys(data?.[0]).map((k) => elNew("th", { textContent: k }));
  elTr.append(...elsTh);
  elThead.append(elTr);
  elTable.append(elThead);
  
  // TBODY
  const elTbody = elNew("tbody");
  data.forEach((item, rowIndex) => {
    const elTr = elNew("tr");
    const elsTd = Object.entries(item).map(([k, v]) => {
      const elTd = elNew("td");
      const elInput = elNew("input", {
        name: `${k}[${rowIndex}]`, // i.e: "id[0]" 
        type: "text",
        value: v,
        oninput() {
          console.info(`Row index: ${rowIndex}\nInput name: ${k}[${rowIndex}]\nInput value: ${elInput.value}`)
        }
      });
      elTd.append(elInput);
      return elTd;
    });
    elTr.append(...elsTd);
    elTbody.append(elTr);
  });
  elTable.append(elTbody);
};


// Usage:
const jsonInput = `[{"id":167915, "type":"variation", "date_created":"2024-04-18T12:09:44"},{"id":167916, "type":"something", "date_created":"2024-06-02T12:15:51"}]`;
addData(jsonInput, "#outputTable", "");
<table id = "outputTable"></table>

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