You need to
- Create a row for each feature
- Create a
td for each plan
- Conditionally display a checkmark based on whether the current plan has that corresponding feature
Your initial data looks something similar to this. Just creating an array of objects so that more plans can be added.
const plans = [
{
planName: 'plan A',
features: [
{ name: 'Regulartz' },
{ name: 'King' },
{ name: 'Individual' },
{ name: 'Normal' },
{ name: 'Cal King' }
]
},
{
planName: 'plan B',
features: [
{ name: 'King' },
{ name: 'Individual' },
{ name: 'Normal' },
{ name: 'Queen' }
]
}
]
In render method, you could use array methods like some to check each plan and its nested features. But, it becomes very expensive operation because you'd have to do it for every td cell. So, you could create an object lookup which has each plan as key and the each feature as that plan's nested key. Also, create a unique Set of all the features in all plans.
const mapper = { },
allFeaturesSet = new Set();
for (const { planName, features } of plans) {
mapper[planName] = {};
for (const { name } of features) {
mapper[planName][name] = true;
allFeaturesSet.add(name)
}
}
const allFeatures = Array.from(allFeaturesSet) // convert set to array
If you have a relational database, you could get this type of data from the server itself. You could do a join between the features and the plans table to get each plan and it's feature mapping. But, since you have arrays, you'd have to loop and create a mapper.
You could also get the unique plans in a separate call like this:
const allFeatures = Array.from(
new Set(plans.flatMap(a => a.features.map(a => a.name)))
);
In render, loop through the plans and create headers for each plan. Loop through each feature and create a row. Inside tr. loop through the plan and check if the mapper object has an entry for the current plan and feature and conditionally display the data
<table>
<thead>
<tr>
{plans.map(a => <th>{a.planName}</th>)}
</tr>
</thead>
{allFeatures.map(f => (
<tr>
{plans.map(a => <td>{mapper[a.planName][f] ? f : '--'}</td>)}
</tr>
))}
</table>
Here's a stackblitz demo
Snippet:
function App() {
const plans = [
{
planName: 'planA',
features: [
{ name: 'Regulartz' },
{ name: 'King' },
{ name: 'Individual' },
{ name: 'Normal' },
{ name: 'Cal King' }
]
},
{
planName: 'planB',
features: [
{ name: 'King' },
{ name: 'Individual' },
{ name: 'Normal' },
{ name: 'Queen' }
]
}
];
const allFeatures = Array.from(
new Set(plans.flatMap(a => a.features.map(a => a.name)))
);
const mapper = {};
for (const { planName, features } of plans) {
mapper[planName] = {};
for (const { name } of features)
mapper[planName][name] = true;
}
return (
<table>
<thead>
<tr>
{plans.map(a =>
<th>{a.planName}</th>
)}
</tr>
</thead>
{allFeatures.map(f => (
<tr>
{plans.map(a => (
<td>{mapper[a.planName][f] ? f : '--'}</td>
))}
</tr>
))}
</table>
);
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
table {
border-collapse: collapse;
}
th, tr, td {
border: 1px solid black;
padding: 5px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
sizesarray?'---', but thats just my opinion. Would this solve the problemarr1.map(val => arr2.some(x => x.name == val.name) ? val.name : '---')? But we still don't know which array we're comparing the others to or maybe we're comparing all arrays against each other, in which case this wouldn't make sense :(["king", "individual", normal", "---"]