Я создаю входные данные в таблице через цикл. Сначала я создаю новую ячейку
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/
Переходим к делу: вам следует объявлять переменные с помощью let
или const
, а не var
.
@Pointy Я предполагаю, что это «псевдо»-код, и ОП хочет получить фактический идентификатор ввода, который вызвал onchange
@DarkBee нет, ОП явно использует что-то, что генерирует значения идентификаторов, а затем в коде, опубликованном в верхней части вопроса, сгенерированный идентификатор используется для создания нового элемента ввода.\
На самом деле это правда. Тогда ваше предложение тоже должно сработать, но Дэвид указал в ответе, о чем я думал / имел в виду.
Если ему просто нужно оповестить себя id
, вы можете получить к нему прямой доступ:
input.onchange = function() {
alert(this.id);
}
переменные внутри циклов for, объявленные с помощью var, имеют область действия функции. Вы можете использовать объявления на уровне блока, const/let, слушать других, пока они указывают решение, или сделать эту уродливую вещь, которая захватывает переменную:
input.onchange = ((id) => function() {
alert(id);
})(thisInputID)
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>
Вы разместили недостаточно кода, чтобы прояснить это, но объявление
thisInputID
, вероятно, является ключом к проблеме. Как и где это декларируется? Есть ли какая-то петля? Как это выглядит?