Your first option would be provide a fixed table, but as you've started down the data-driven route, let's rule that out.
A fixed table would be where the table is pre-defined in the HTML and then you add data to it.
A hardcoded table would be where assumptions are made about the data, such as it having 31 columns. So you can write your loop as a basic for
loop:
for (var i=0;i<=31;i++) {
tr.append("<th>" + i + "</th>");
In both the above cases, if your data changes (eg add a column 31
) then you'd need to update the HTML. Which is why we write data-driven applications (assuming we can trust the data source...)
Sorting the JSON [columns] - "id" "nama" "bulan" "tahun" thead as the first columns
This answer provides details here. In summary, "numeric" keys are displayed first and then your alphabetical keys.
To get them in the order you want, you could change your data so it's not numeric, eg from
[ { "2": { "shift": "9" ...
to
[ { "key2": { "shift": "9" ...
then ensure your other columns are at the front and tweak your code to exclude the prefix.
Assuming you don't want to change your keys, you can change your thead
loop so that it finds alpha keys first (two loops), eg:
let tr = $("<tr />");
$.each(Object.keys(myObj.data[0]), function(_, key) {
if (parseInt(key)) return;
tr.append("<th>" + key + "</th>");
});
$.each(Object.keys(myObj.data[0]), function(_, key) {
if (!parseInt(key)) return;
tr.append("<th>" + key + "</th>");
});
tr.appendTo(thead);
Bit of DRY here, but as long as the tr.append
isn't too long, no-one should complain.
You'll also need to change the tbody loop to get them in the correct order
However, when combined with the next requirement, there's no need for the above as there's only one non-numeric header
Make condition only object "nama" and all the number object appear on the table (1-31).
In this case, add the nama
column first, then the numeric columns, using the same condition as above, eg:
let tr = $("<tr />");
tr.append("<th>nama</th>");
$.each(Object.keys(myObj.data[0]), function(_, key) {
if (!parseInt(key)) return;
tr.append("<th>" + key + "</th>");
});
tr.appendTo(thead);
Again, this will need changes to the data loop - which we can make easier below.
What if some of JSON object array not having same number (ex. one array is 1-30, and other is 1-31. Then the 1-30 td is blank on the last column)
In this case you should parse the list first to find all the keys you're interested in, then create the same keys on each tr.
In the simple form where data[0] contains all the required headers, it would be:
let cols = [];
cols.push("nama");
$.each(Object.keys(myObj.data[0]), function(_, key) {
if (!parseInt(key)) return;
cols.push(key);
});
but we wants to get other columns as well - in your fiddle, I've removed "1" from the first data and added "33" to 2nd data to show these working (missing 32 so it's not in the columns)
let cols = [];
$.each(myObj.data, (, data) => {
$.each(Object.keys(data), function(, key) {
if (!parseInt(key)) return;
if (!cols.includes(key))
cols.push(key);
});
});
// sort here using a numeric sort
cols = cols.sort(function(a, b) { return a - b; });
// add specific columns at the front
cols.unshift("nama");
They need to be sorted to get the initially-missing "1" back to the start.
Alternatively you could get a min-max values here are render all between, which would also output the "32".
Then add to the table, by looping the cols, not the data keys
let tr = $("<tr />");
$.each(cols, (_,key) => tr.append("<th>" + key + "</th>") );
tr.appendTo(thead);
$.each(myObj.data, function(_, obj) {
tr = $("<tr />");
$.each(cols, (_,key) => {
tr.append("<td>"
+ (!obj[key]
? ""
: (obj[key].namashift
? obj[key].namashift
: obj[key]))
+ "</td>")
});
tr.appendTo(tbody);
});
Where !obj[key] ? ""
checks for missing values and obj[key].namashift ?
is your original check for numeric key with namashift vs namashift itself. You can expand this to if / else
for your own clarity.
Updated fiddle: https://jsfiddle.net/rz26xabm/
Alternatively, if you can change the JSON, then add a "header" row to describe how to build the table and loop on that.