I would appreciate feedback especially if you would be embarrassed by this code, or if I was on your team and you would expect better and/or you would mention something.
This code was derived from comments made on Function To Add DOM Nodes (it also lead to new ideas that are unique to this post).
If there are things that could improve performance definitely suggest them (as this code will be called frequently and there will be a lot of data in the browser).
If there is code that should be reused just point it out for me!
This is a javascript function that will accept an array of objects (from a database or websocket) and then spit out HTML <ul> lists.
I also tried to make the code more robust by allowing an array of objects or a single object to be sent and the object(s) properties to be sent in any order but still maintain order for the HTML output.
The code works -- but I am "self-taught" and always learning. I want to be producing professional looking/behaving code and the feedback here will inform all my projects.
Any insights into style or approach would be welcomed. Get the red marker out!
Javascript Code
function addChildren(children) {
// Add a single child to the DOM (if array not passed)
if (!Array.isArray(children)) {
addChildToDOM(children);
return;
}
// Add children to the DOM
for (const child of children) {
addChildToDOM(child);
}
}
// Order the child's DOM elements
/* Places the properties in the correct order -- but you can override the default order.
Noteably if there are missing properties they will appear at the end of the object (to improve code maintainability) */
function orderChildObject(child, propertyOrder= ["group","flags","firstName","lastName","guardian","checkIn","notes","phone"]) {
let objectOrder = new Object();
propertyOrder.forEach(function(value, index, array) {
objectOrder[value] = null;
});
objectOrder = Object.assign(objectOrder, child);
return objectOrder;
}
function addChildToDOM(child) {
// Ensure that required properties exist or stop
if (!(child.hasOwnProperty("firstName") || child.hasOwnProperty("lastName"))
|| !child.hasOwnProperty("phone")) {
// @TODO add warning to user interface
console.log("Child missing required data and could not be displayed");
return;
}
// Ensure properties are ordered properly in the DOM
child = orderChildObject(child);
// Function variables
const childList = document.getElementById("childList"); // Top-level DOM node for child nodes
const childId = child.firstName + child.lastName + child.phone;
let ul; // Top-level of this child's node on the DOM
// Delete child from DOM if overwriting
if(document.getElementById(child.id)){
ul = document.getElementById(child.id);
ul.remove();
}
// Add ul child to DOM
ul = document.createElement("ul"); // Top-level of child on DOM
ul.id = childId;
childList.appendChild(ul);
// Assign <ul> to a group
if (child.group) {
ul.classList.add(child.group);
} else {
ul.classList.add("unassigned");
}
// Add the properties to the child as <li>s
let childKeys = Object.keys(child);
for (let property in childKeys) {
const key = childKeys[property];
const value = child[childKeys[property]];
if(key === "id") continue; // Skip adding the id as an <li> (added as #id on <ul>)
const li = assignChildProperty(key, value);
ul.appendChild(li);
}
function assignChildProperty(key, value) {
// If child property value is an object
if (typeof (value) === "object") {
// Add <li> to child's <ul> node and create a <ul> for this property
const outerli = document.createElement("li");
outerli.classList.add(key);
const ul = document.createElement("ul");
// Run through each of the nested objects and add <li>
for (let property in value) {
const li = document.createElement("li");
li.innerText = value[property]; // the object's value
li.classList.add(key); // the outer object's class key
// if the object is an array, don't add the array index to class
if (!Array.isArray(value)) {
li.classList.add(property); // the object's key
}
// add the <li> to the <ul>
ul.appendChild(li);
}
// add the <ul> to the outer <li> to be returned to the outer <ul>
outerli.appendChild(ul);
return outerli;
}
// If child property is a simple value (ie. string)
const li = document.createElement("li");
li.classList.add(key);
li.innerText = value;
return li;
}
}
The input from an AJAX call or a websocket push:
// example use of data from AJAX database call being implemented
addChildren([
{
group: 'prek',
firstName: "Bobby",
lastName: "Fisher",
group: "prek",
checkIn: "9:14am",
phone: "ewqrqr3452",
},
{
group: "grade1",
firstName: "Anne",
lastName: "Gables",
guardian: {firstName: "Green", lastName: "Gables"},
flags: ['peanuts','bees'],
checkIn: "9:14am",
phone: "ewqrqr3452",
test: "this is a test",
}
]);
// example use of data from a websocket push that would overwrite a node
addChildToDOM( {
id: "BobbyFisherewqrqr3452",
group: "grade1",
firstName: "Bobby",
lastName: "Fisher",
guardian: {firstName: "Green", lastName: "Gables"},
checkIn: "9:14am",
phone: "ewqrqr3452",
test2: "this is a second test",
});
HTML Output
<main id="childList"><!-- where the output hooks on to the HTML -->
<ul id="BobbyFisherewqrqr3452" class="prek">
<li class="group">prek</li>
<li class="firstName">Bobby</li>
<li class="lastName">Fisher</li>
<li class="guardian">
<ul>
<li class="guardian firstName">Green</li>
<li class="guardian lastName">Gables</li>
</ul>
</li>
<li class="checkIn">9:14am</li>
<li class="phone">ewqrqr3452</li>
</ul>
</main>
Note: I am using Babel for transpiling (added)