import { UiElement } from "../UiElement.js";
import "./EditableTable.css";
/**
* Represents an editable table UI element.
* @extends UiElement
* @memberof vef.ui.table
*/
class EditableTable extends UiElement {
classes = "editable-table";
template = `
<table>
<thead>
<tr></tr>
</thead>
<tbody></tbody>
</table>
<a href="#" class="btn-add-row">+ Add</a>
`;
/**
* Creates an instance of EditableTable.
* @param {HTMLElement} target - The target element to attach the table to.
* @param {Array} columns - The columns of the table.
* @param {Array} values - The initial values for the table rows.
*/
constructor(target, columns, values) {
super(target);
this.columns = columns || [];
this.datalists = {};
this.setHtml(this.template);
this.setClass(this.classes);
this.tbody = this.query("tbody");
this.addRowButton = this.query(".btn-add-row");
this.addRowButton.addEventListener("click", (e) => {
e.preventDefault();
this.addRow();
});
this.getElement().classList.add("editable-table");
this.getElement().appendChild(this.addRowButton);
this.columns.forEach(column => {
this.query("thead tr").insertAdjacentHTML("beforeend", `<td>${column.name}</td>`)
this.extractAndCreateDataLists(values, column.key, column.name);
});
this.Row(values);
}
/**
* Extracts values from an array of objects and creates datalists for a specific column.
* @param {Array} array - The array of objects.
* @param {string} key - The key to extract values from.
* @param {string} name - The name of the column.
*/
extractAndCreateDataLists(array, key, name) {
const values = this.createArrayValues(array, key);
this.createList(values, name);
}
/**
* Creates an array of values from an array of objects based on a specific key.
* @param {Array} ar - The array of objects.
* @param {string} key - The key to extract values from.
* @returns {Array} The array of values.
*/
createArrayValues(ar, key) {
return ar.map(obj => obj[key]);
}
/**
* Creates a datalist for a specific column.
* @param {Array} arr - The array of values.
* @param {string} name - The name of the column.
*/
createList(arr, name) {
const uniArr = [...new Set(arr)];
const dataList = document.createElement("datalist");
dataList.id = name;
uniArr.forEach(element => {
const option = document.createElement('option');
option.value = element;
option.text = element;
dataList.appendChild(option);
});
this.getElement().appendChild(dataList);
this.datalists[name] = dataList;
}
/**
* Adds a new row to the table.
*/
addRow() {
const tr = document.createElement("tr");
this.columns.forEach(column => {
const listName = column.key;
const td = document.createElement("td");
const input = document.createElement("input");
input.type = 'search';
input.setAttribute('list', listName);
td.appendChild(input);
tr.appendChild(td);
});
const td = document.createElement("td");
const deleteButton = document.createElement("a");
deleteButton.href = "#";
deleteButton.addEventListener("click", e => {
e.preventDefault();
e.currentTarget.parentNode.parentNode.remove();
})
deleteButton.className = "EditableTableRowRemove"
deleteButton.innerHTML = "<i class='fas fa-times'></i>";
td.appendChild(deleteButton);
tr.appendChild(td);
this.tbody.appendChild(tr);
}
/**
* Adds rows to the table based on an array of existing values.
* @param {Array} array_of_existing - The array of existing values.
*/
Row(array_of_existing) {
array_of_existing.forEach(obj => {
const tr = document.createElement("tr");
let table_rows = this.columns.map(column => column.key);
let countr = 0;
table_rows.forEach(listName => {
const td = document.createElement("td");
const input = document.createElement("input");
input.type = 'search';
input.setAttribute('list', listName);
input.value = obj[table_rows[countr]]
td.appendChild(input);
tr.appendChild(td);
++countr;
});
const td = document.createElement("td");
const deleteButton = document.createElement("a");
deleteButton.href = "#";
deleteButton.className = "EditableTableRowRemove"
deleteButton.addEventListener("click", e => {
e.preventDefault();
e.currentTarget.parentNode.parentNode.remove();
})
deleteButton.innerHTML = "<i class='fas fa-times'></i>";
td.appendChild(deleteButton);
tr.appendChild(td);
this.tbody.appendChild(tr);
});
}
/**
* Gets the values from the table.
* @returns {Array} The array of values.
*/
getValues() {
const rows = this.tbody.querySelectorAll("tr");
const valuesArray = [];
rows.forEach(row => {
const inputs = row.querySelectorAll("input[type='search']");
const values = {};
inputs.forEach(input => {
const columnname = input.getAttribute('list');
if (columnname) {
values[columnname] = input.value;
}
});
valuesArray.push(values);
})
return valuesArray;
}
/**
* Clears the table.
*/
clearTable() {
const trs = this.tbody.querySelectorAll("tr");
trs.forEach(tr => {
tr.remove();
})
}
}
export { EditableTable };