How to count the value in an nested array in Vue.js?

Viewed 116

I'm trying to count how many hr_checked = false by specific user on a nested array inside an array in an Vue.js. Here's a snippet of array code:

userlistes: [
            {
              id: 2,
              username: "Larry",
              department_id: 3,
              department: {
                department_name: "IT",
                id: 3,
              },
              worklists: [
                {
                  id: 278,
                  user_id: 2,
                  task_id: 1,
                  date: "2021-07-30",
                  hour: 2,
                  description: "A",
                  is_overtime: false,
                  overtime_hour: 0,
                  task: {
                    taskname: "Task A",
                  },
                  hr_checked: false,
                },
                {
                  id: 277,
                  user_id: 2,
                  task_id: 1,
                  date: "2021-07-30",
                  hour: 3,
                  description: "B",
                  is_overtime: false,
                  overtime_hour: 0,
                  task: {
                    taskname: "Task B",
                  },
                  hr_checked: false,
                },
              ],
            },
            {
              id: 4,
              username: "Tom",
              department_id: 2,
              department: {
                department_name: "Business",
                id: 2,
              },
              worklists: [
                {
                  id: 259,
                  user_id: 4,
                  task_id: 7,
                  date: "2021-07-27",
                  hour: 6.5,
                  description:
                    "A",
                  is_overtime: false,
                  overtime_hour: 0,
                  task: {
                    taskname: "Task A",
                  },
                  hr_checked: false,
                },
                {
                  id: 260,
                  user_id: 4,
                  task_id: 7,
                  date: "2021-07-27",
                  hour: 0.5,
                  description: "B",
                  is_overtime: false,
                  overtime_hour: 0,
                  task: {
                    taskname: "Task B",
                  },
                  hr_checked: false,
                },
              ],
            },
          ],

And i tried to used Vue computed property to implement this:

  computed: {
    countCheck() {
      return this.userlistes.filter((userliste) => {
        return userliste.workhours.reduce((sum, workhour) => {
          if (workhour.hr_checked === false) {
            sum++;
          }
          return sum;
        }, 0);
      });
}

I want to get the count of the values inside the nested array's 'hr_checked'.

the returning result should be like:

Larry: unchecked 2

Tom: unchecked 2

Is there any way to do this in Vue.js? or i'm use wrong function??

3 Answers

Try to map the wrapping array then reduce the nested one :

return this.userlistes.map((item)=>({username:item.username,
              unchecked :item.worklists.reduce((sum, workhour) => {
                if (workhour.hr_checked === false) {
                    sum++;
                 }
               return sum;
           }, 0)}))

let userlistes = [{
    id: 2,
    username: "Larry",
    department_id: 3,
    department: {
      department_name: "IT",
      id: 3,
    },
    worklists: [{
        id: 278,
        user_id: 2,
        task_id: 1,
        date: "2021-07-30",
        hour: 2,
        description: "A",
        is_overtime: false,
        overtime_hour: 0,
        task: {
          taskname: "Task A",
        },
        hr_checked: false,
      },
      {
        id: 277,
        user_id: 2,
        task_id: 1,
        date: "2021-07-30",
        hour: 3,
        description: "B",
        is_overtime: false,
        overtime_hour: 0,
        task: {
          taskname: "Task B",
        },
        hr_checked: false,
      },
    ],
  },
  {
    id: 4,
    username: "Tom",
    department_id: 2,
    department: {
      department_name: "Business",
      id: 2,
    },
    worklists: [{
        id: 259,
        user_id: 4,
        task_id: 7,
        date: "2021-07-27",
        hour: 6.5,
        description: "A",
        is_overtime: false,
        overtime_hour: 0,
        task: {
          taskname: "Task A",
        },
        hr_checked: false,
      },
      {
        id: 260,
        user_id: 4,
        task_id: 7,
        date: "2021-07-27",
        hour: 0.5,
        description: "B",
        is_overtime: false,
        overtime_hour: 0,
        task: {
          taskname: "Task B",
        },
        hr_checked: false,
      },
    ],
  },
]

let mapped = userlistes.map((item) => ({
  username: item.username,
  unchecked: item.worklists.reduce((sum, workhour) => {
    if (workhour.hr_checked === false) {
      sum++;
    }
    return sum;
  }, 0)
}))

console.log(mapped)

Here is another solution:

link to codesandbox example

Code in computed props:

  computed: {
    getHRByUser() {
      let res = [];
      let reducer = (sum, workitem) => {
        if (workitem.hr_checked === false) {
          sum++;
        }
        return sum;
      };
      for (const i in this.userlistes) {
        let inactiveHRCount = this.userlistes[i].worklists.reduce(reducer, 0);
        res.push({
          username: this.userlistes[i].username,
          inactiveHRCount: inactiveHRCount,
        });
      }
      return res;
    },
  }

But Boussadjra Brahim proposed a bit more elegant solution in this case.

computed is fine as your data are dynamic and the function would run everytime the data changes. I would use the above example

countCheck() {
      let count = 0
      this.userlistes.filter((userliste) => {
        if (userliste.workhours && userliste.workhours.hr_checked) {
          count++
        }
      })
      return count
  }
Related