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)!

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
}]));

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

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.