I have an array of users
containing user name with their rules on my practice project
I have generated a table in HTML from that array in JS, So I can
change the status of any user rule by toggling on cell, or toggling all rules by clicking on name of user, or deny or grant rules for all users by clicking on column vertically!
BUT I want to update the original array users
rules, if the rules of any user change;
In other words How can I make the array in JS synchronize with the table in HTML.
const users = [ { name: "Admin", rules: { Create: true, Read: true, Update: true, Delete: true }, }, { name: "Developer", rules: { Create: true, Read: true, Update: false, Delete: true }, }, { name: "Customer", rules: { Create: false, Read: true, Update: false, Delete: false }, }, ]; let rules = ["Create", "Read", "Update", "Delete"]; let status = { "": "red", green: "red", red: "green", }; let icons = { "": "๐ฅ", green: "๐ฅ", red: "๐ฉ", }; const table = document.createElement("table"); const thead = table.createTHead(); const tr = thead.insertRow(); const th = tr.appendChild(document.createElement("th")); th.appendChild(document.createTextNode("Users")); rules.forEach((rule, i) => { const th = tr.appendChild(document.createElement("th")); th.appendChild(document.createTextNode(rule)); th.setAttribute("status", ""); th.onclick = (e) => { const cols = [ ...document.querySelectorAll(`tbody tr td:nth-child(${i + 2})`), ]; cols.forEach((col) => { col.textContent = icons[e.target.getAttribute("status") ?? ""]; }); e.target.setAttribute( "status", status[e.target.getAttribute("status") ?? ""] ); }; }); const tbody = table.createTBody(); users.forEach((user) => { const tr = tbody.insertRow(); const td = tr.appendChild(document.createElement("td")); td.appendChild(document.createTextNode(user.name)); td.onclick = (e) => { rulesUser = [...td.parentElement.children]; rulesUser.slice(1).forEach((rule) => { rule.textContent = icons[e.target.getAttribute("status") ?? ""]; }); e.target.setAttribute( "status", status[e.target.getAttribute("status") ?? ""] ); }; rules.forEach((rule) => { const td = tr.insertCell(); td.appendChild( document.createTextNode( Object.entries(user.rules) .filter((entry) => entry[1] == true) .map((entry) => entry[0]) .includes(rule) ? "๐ฉ" : "๐ฅ" ) ); td.setAttribute( "status", Object.entries(user.rules) .filter((entry) => entry[1] == true) .map((entry) => entry[0]) .includes(rule) ? "green" : "red" ); td.onclick = (e) => { e.target.textContent = icons[e.target.getAttribute("status") ?? ""]; e.target.setAttribute( "status", status[e.target.getAttribute("status") ?? ""] ); }; }); }); document.body.appendChild(table);
* { font-family: sans-serif; } table { border-collapse: collapse; border: 1px solid; } td, th { padding: 5px 10px; text-align: center; border: 1px solid; cursor: pointer; } thead th { background-color: gray; } tbody th { background-color: lightgray; } thead th:first-child { background-color: lightblue; }
Any feedback or suggestion to make the code better, I'd be really grateful if somebody could help me with this problem so I can continue building my practice project. Thanks โค๏ธ