0

I have two sets of arrays, one I'm using for the headers (columns) of a table, and the other for the rows of the table.

const headers = [
 {
 text: 'Dessert (100g serving)',
 align: 'left',
 sortable: false,
 value: 'name',
 visible: true
 },
 { text: 'Calories', value: 'calories', visible: true },
 { text: 'Fat (g)', value: 'fat', visible: true },
 { text: 'Carbs (g)', value: 'carbs', visible: true },
 { text: 'Protein (g)', value: 'protein', visible: true },
 { text: 'Iron (%)', value: 'iron', visible: true }
]
const desserts = [
 {
 name: 'Frozen Yogurt',
 calories: 159,
 fat: 6.0,
 carbs: 24,
 protein: 4.0,
 iron: '1%'
 },
 {
 name: 'Ice cream sandwich',
 calories: 237,
 fat: 9.0,
 carbs: 37,
 protein: 4.3,
 iron: '1%'
 },
 {
 name: 'Eclair',
 calories: 262,
 fat: 16.0,
 carbs: 23,
 protein: 6.0,
 iron: '7%'
 },
 {
 name: 'Cupcake',
 calories: 305,
 fat: 3.7,
 carbs: 67,
 protein: 4.3,
 iron: '8%'
 }
]

What I'm trying to achieve is to give the user the ability to be able to decide which columns of the data they'd like to view in the table.

I'm using Vue.js, so my attempts have been to set out a collection of checkboxes, each is v-bind as a header from the headers collection.

I'm doing this using the following:

computed: {
 filteredHeaders () {
 return this.headers.filter(header => header.visible)
 }
}

This works as expected, horrah! The table column headers change based on the columns selected with the checkboxes.

The bit I'm stuck on is trying to filter the row data (or desserts) based on the selected columns (or filteredHeaders).

I've tried the following:

computed: {
 ...
 filteredItems () {
 return this.desserts.filter(dessert => {
 return this.filteredHeaders.some(header => {
 return Object.keys(header).some(prop => {
 return dessert[prop] != header[prop] && header.visible
 })
 })
 })
 }
}

Even though there are no errors being thrown, the result of filteredItems remains that of the original desserts and the properties that should be excluded (when visible gets set to false by the collection of checkboxes) are still being displayed.

I'm sure I'm close, but close doesn't get me that cigar (as the saying goes)!

asked Sep 8, 2019 at 19:34

1 Answer 1

1

This method should roughly achieve what you're looking for:

const headers = [{
 text: "Dessert (100g serving)",
 align: "left",
 sortable: false,
 value: "name",
 visible: true
 },
 {
 text: "Calories",
 value: "calories",
 visible: true
 },
 {
 text: "Fat (g)",
 value: "fat",
 visible: true
 },
 {
 text: "Carbs (g)",
 value: "carbs",
 visible: true
 },
 {
 text: "Protein (g)",
 value: "protein",
 visible: true
 },
 {
 text: "Iron (%)",
 value: "iron",
 visible: true
 }
];
const desserts = [{
 name: "Frozen Yogurt",
 calories: 159,
 fat: 6.0,
 carbs: 24,
 protein: 4.0,
 iron: "1%"
 },
 {
 name: "Ice cream sandwich",
 calories: 237,
 fat: 9.0,
 carbs: 37,
 protein: 4.3,
 iron: "1%"
 },
 {
 name: "Eclair",
 calories: 262,
 fat: 16.0,
 carbs: 23,
 protein: 6.0,
 iron: "7%"
 },
 {
 name: "Cupcake",
 calories: 305,
 fat: 3.7,
 carbs: 67,
 protein: 4.3,
 iron: "8%"
 }
];
const filterRows = (rows, headers) => {
 // Map over the full list of rows to filter down
 return rows.map(row => {
 // Create a new row to return to avoid mutating
 const filteredRow = {};
 // Loop through each header and copy the row value corresponding to that header value
 headers.forEach(header => {
 filteredRow[header.value] = row[header.value];
 });
 // Return the copied and filtered row
 return filteredRow;
 });
};
console.log(filterRows(desserts, headers));
console.log(filterRows(desserts, [{
 text: "Iron (%)",
 value: "iron",
 visible: true
}]));

answered Sep 8, 2019 at 19:40
Sign up to request clarification or add additional context in comments.

1 Comment

I'm going to accept this as the answer as it's the easiest to understand. FYI here's my implementation of the solution - CodePen

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.