EDIT: I've updated my watcher and recall the function to update the percentage live, but it's still not verbose enough to check and update all changed objs.
watch: {
tableData(newVal, oldVal) {
const changedObjIndex = this.tableData.findIndex((obj) => {
return obj.status === "In Progress"
})
console.log(`changed obj`, changedObjIndex)
this.handleDisplayStatus(changedObjIndex)
console.log(
`obj that changed`,
this.tableData[changedObjIndex].completion_progress
)
},
},
Problem
I have a table that shows the details and progress of a video(s) upload. The progress bar is where I am having trouble updating it live (more on this below).
I have a blank tableData array in my data that is filled when the component is rendered with a handleDisplayStatus
function. This method only runs once obviously, so I was planning on putting a watcher on the tableData array and then rerunning the handleDisplayStatus
function if there is a change. I initially went with:
this.tableData.every((item) =>
console.log(
`completion progress from watcher`,
item.completion_progress
)
)
However .every
only returns a boolean and while it would rerun the handleDisplayStatus
function, that function takes an index, _row
so that doesn't seem to be the fix.
Also putting this.handleDisplayStatus(index, _row)
in the watcher will give this error in the console Error in callback for watcher "tableData": "ReferenceError: index is not defined"
.
Which makes sense because that function needs the indexes (_row param is not being used I think).
From there I went with .findIndex
, but again that just gives me the first element that satisfies the condition. Since the table can have multiple videos loading at the same time, this is not the correct fix either.
tableData(newVal, oldVal) {
const changedObjIndex = this.tableData.findIndex((obj) => {
return obj.status === "In Progress"
})
console.log(changedObjIndex)
}
As I mentioned, everything works fine, but I need a page refresh to show the updated number. We are purposely not using socket.io for this; even though I think it's probably a good idea.
Any ideas of how I can get this function to call properly and get the percentages to update in real time? Even the old :key
to force a rerender doesn't want to work here.
Any help or guidance would be greatly appreciated!
NOTE:
my progress bar just takes in a percentage
prop as a number to render and is pretty straightforward. If you need to see that code as well I can edit this post!
tableData Array of Objs with key/values (NOTE: the task_status should be: "IN PROGRESS", but I couldn't edit that on the mySQL workbench)
Method that needs to be recalled
handleDisplayStatus(index, _row) {
if (this.tableData[index].task_status == "IN PROGRESS") {
let trainingProcessId = this.tableData[index].training_process_id
this.tableData[index].intervalId = setInterval(() => {
if (
this.tableData[index].completion_progress != 100 &&
this.tableData[index].task_status == "IN PROGRESS"
) {
getTrainingProcessInfo({
trainingProcessId: trainingProcessId,
}).then((res) => {
let jsonObj = JSON.parse(JSON.stringify(res.data))
this.tableData[index].completion_progress =
jsonObj.completion_progress
})
} else {
clearInterval(this.tableData[index].intervalId)
}
}, 6000)
}
return this.tableData[index].task_status
}
template (fwiw)
<template>
<div>
<el-card >
<div style="margin-left: 5px" >
<el-table
ref="multipleTable"
v-loading="listLoading"
:data="tableData"
id="el-table"
>
<el-table-column
:label="$t('training_monitor_content.table_column_5')"
align="center"
>
<template slot-scope="scope">
<ProgressBar
:key="scope.row.user"
style="width: 100%; height: 20px; flex-shrink: 0"
:percentage="scope.row.completion_progress"
/>
</template>
</el-table-column>
</el-table>
</div>
</el-card>
</div>
</template>
CodePudding user response:
If I understood you correctly try with deep watch:
watch: {
tableData: {
handler(newValue) {
newValue.forEach((obj, idx) => {
if (obj.status === 'In Progress') this.handleDisplayStatus(idx)
});
},
deep: true
}
}