Reputation: 1563
I have a data structure that is a nested object. It’s a map that has unique id keys.
Each key then contains another map which consists of another set of unique id keys (_id corresponding to Mongo documents). And each one of these keys contains a Mongo Document.
https://i.sstatic.net/1IeTJ.jpg is an example of how the data structure looks like in Chrome dev tools.
I want to iterate over this in Blaze. My goal is to have a header that displays the top-level keys (1 & 2 in this example)…and then for each top level-key, have a table where each row is a nested document.
I understand that Blaze can only iterate through arrays and cursors and not JS Objects. https://github.com/meteor/meteor/issues/3884 And so I used _.pair to serialize my nested object into an array and here's my result https://i.sstatic.net/qojXj.jpg
I’m having trouble getting what I want with the 2D array though. Because now my top-level key (1 & 2 in this example) are at the first index of an array. I can’t figure out how to access this inside an each.
Here’s my full goal in a nutshell I.e.
{{#each 2dArray}}
print {{this[0]}}
<table>
{{#each this[1]}}
<tr>{{nestedThis.data}}</tr>
{{/each}}
</table>
{{/each}}
Does anybody know how to do this or is there a better way to structure my data too? Thanks
Upvotes: 0
Views: 363
Reputation: 449
You should be able to restructure your data as follows
input = {
1: {
bob001: {_id: "bob001", name: "Bob" },
jim002: {_id: "jim002", name: "Jim" },
},
2: {
kim001: {_id: "kim001", name: "Kim" },
sue002: {_id: "sue002", name: "Sue" },
}
}
console.log(input);
output = Object.keys(input).map(key => {
return {
key: key,
data: Object.values(input[key]).map(row => {
return Object.keys(row).map(k => {
return {key: k, data: row[k]};
});
})
}
})
console.log(output);
In your component, restructure the input into a new ReactiveVar
. Do this in an $autorun
, assuming the input is reactive (thanks @Jankapunkt):
Template.my_template.onCreated({
this.formattedData = new ReactiveVar([]);
this.$autorun(() => {
const input = this.input; // get this from somewhere reactive?...
this.formattedData = Object.keys(input).map(key => {
return {
key: key,
data: Object.values(input[key]).map(row => {
return Object.keys(row).map(k => {
return {key: k, data: row[k]};
});
})
}
})
})
})
Then you can display it using blaze:
{{#each formattedData}}
print {{key}}
<table>
{{#each data}}
<tr>
{{#each this}}
<td>{{key}}: {{data}}</td>
{{/each}}
</tr>
{{/each}}
</table>
{{/each}}
Upvotes: 2