menu

Questions & Answers

How can I remove an item from an array of objects nested in an array of objects using VUE 3?

I have an order form where a user can add JOBS and each JOB is broken down into LABOR lines and PARTS lines like so:

JOB1

  • LABOR1
  • LABOR2
  • PART1
  • PART2

JOB2

  • LABOR1
  • LABOR2
  • PART1
  • PART2

I have set up the data as an array of objects where each JOB is an object and within that JOB object there are LABOR and PART arrays with objects for each line. I can add new JOBS and LABOR and PARTS to each JOB but I cannot, for the life of me, figure out how to remove a single LABOR or PART line from the nested arrays.

I have:

const jobs = ref([
  {
    jobId: idGen(),             // idGen() is simply a unique ID generator
    jobTitle: 'Job 1',
    jobLabor: [],
    jobPart: []
  }
])

const addJob = () => {        // This function works fine and adds a new JOB to the order
  jobs.value.push({
    jobId: idGen(),
    jobTitle: 'New Job',
    jobLabor: [],
    jobPart: []
  })
}

const addLabor = (addToJobId) => {
  const job = jobs.value.filter(job => jobId === addToJobId)
  job[0].jobLabor.push({
    laborId: idGen(),
    description: '',
    quantity: 1,
    amount: 0                  // This function adds a LABOR line to job
  })
}

const addPart = (addToJobId) => {
  const job = jobs.value.filter(job => jobId === addToJobId)
  job[0].jobPart.push({
    laborId: idGen(),
    description: '',
    quantity: 1,
    amount: 0                  // This function adds a PART line to job
  })
}

const deleteJob = (deleteJobId) => {        // This function deleted a WHOLE JOB
  jobs.value = jobs.value.filter(job => job.jobId !== deleteJobId)
  if (jobs.value.length === 0) { addJob() }     // Making sure the form is not empty/unusable
}

const deleteLaborLine = (deleteFromJobId, deleteLaborId) => {
  const job = jobs.value.filter(job => job.jobId === deleteFromJobId)
  job[0].jobLabor.filter(labor => labor.laborId !== deleteLaborId)
}

I can't get deleteLaborLine(jobId, laborId) to work. I just want the function to delete ONE labor line from an array of other labor lines within a jobs array. I hope this all makes sense. Any help or insight is appreciated.

1.  const deleteLaborLine = (deleteFromJobId, deleteLaborId) => {
2.      const job = jobs.value.filter(job => job.jobId === dleteFromJobId)
3.      job[0].jobLabor.filter(labor => labor.laborId !== deleteLaborId)
4.  }

Please check the spelling of deleteFromJobId on line no 2 change from dleteFromJobId to deleteFromJobId and try again, it should work fine.

Thanks.

Comments:
2023-01-11 09:00:38
Looks like a typo, It should be deleteFromJobId instead of dleteFromJobId.
Answers(3) :

The issue with the code is in the line

job[0].jobLabor.filter(labor => labor.laborId !== deleteLaborId)

Array.filter simply return an array with the specified condition. As you have written, this will return an array of jobLabour where the laborId !== deleteLaborId, but this will not change your original job[0].jobLabor array.

You can either reassign job[0].jobLabor with the result of this filter as mentioned by @MatijaSirk, or you can simply splice the array after finding the index to delete the node from job[0].jobLabor.

const deleteLaborLine = (deleteFromJobId, deleteLaborId) => {
  const job = jobs.value.filter(job => job.jobId === dleteFromJobId)
  const index = job[0].jobLabor.findIndex(labor => labor.laborId !== deleteLaborId)
  if (index !== -1) {
    job[0].jobLabor.splice(index, 1)
  }
}
Comments:
2023-01-11 09:00:38
Thank you for this! I see how this code works, though it seems more verbose. Do you know if there is any particular benefit to using this version?

Filter doesn't mutate array, you need to explicitly assign its result.

Try replacing last line in deleteLaborLine function with job[0].jobLabor = job[0].jobLabor.filter(labor => labor.laborId !== deleteLaborId).

Comments:
2023-01-11 09:00:38
WOW! It's the same thing I did in deleteJob() and I was only missing the assignment! This had me so frustrated! Thank you for your help @MatijaSirk. You're amazing!
1.  const deleteLaborLine = (deleteFromJobId, deleteLaborId) => {
2.      const job = jobs.value.filter(job => job.jobId === dleteFromJobId)
3.      job[0].jobLabor.filter(labor => labor.laborId !== deleteLaborId)
4.  }

Please check the spelling of deleteFromJobId on line no 2 change from dleteFromJobId to deleteFromJobId and try again, it should work fine.

And second issue is that when you are filtering jobLabor array in line no 3 it will not assign any filter unless you store it

you should follow this or slice method of javascript

job[0].jobLabor = job[0].jobLabor.filter(labor => labor.laborId !== deleteLaborId)

Thanks.

Comments:
2023-01-11 09:00:38
Thank you for catching that. Spelling errors like that can be so frustrating to track down sometimes.