Working on a Vue.js project, I find myself needing to monitor changes in a nested property (isChecked) within a complex component structure. My aim is to execute a method (sumOfChecked) whenever the isChecked property changes in any row or its child rows.
Below is a simplified representation of my component hierarchy:
<template>
<div class="tw-max-w-max">
<div v-for="(row, index) in rows" :key="index">
<fieldset class="tw-grid tw-grid-cols-[2fr_100px_120px_100px_100px_30px] tw-gap-4">
<v-list-item-title class="tw-text-sm tw-flex tw-justify-between tw-items-center">
<span>{{ row.kostenstelleName }}</span>
<v-checkbox
v-model="row.isChecked"
@change="onCheckboxClicked"
/>
</v-list-item-title>
<!-- Other fields omitted for brevity -->
</fieldset>
<KreuztabelleRow
v-if="row.subRows.length"
:is-subitem="true"
:kreuztabelle="{rows: row.subRows}"
/>
</div>
</div>
</template>
<script lang="ts">
import { Component, Emit, Prop, Vue, Watch } from 'vue-property-decorator';
import KreuztabelleRow from './KreuztabelleRow.vue';
@Component({
components: { KreuztabelleRow },
})
export default class KreuztabelleRow extends Vue {
@Prop({ required: true, type: Object }) kreuztabelle;
@Prop({ required: false, default: false }) isSubitem;
get rows() {
return this.kreuztabelle?.rows || [];
}
@Emit('sum-of-checked')
onCheckboxClicked() {
return this.sumOfChecked();
}
sumOfChecked() {
const calculateSum = (rows) => {
return rows.reduce((sum, row) => {
if (row.isChecked) {
sum += row.summe || 0;
}
if (row.subRows && row.subRows.length > 0) {
sum += calculateSum(row.subRows);
}
return sum;
}, 0);
};
return calculateSum(this.rows);
}
@Watch('rows', { immediate: true, deep: true })
onRowsChange(newRows) {
newRows.forEach((row) => {
this.$watch(() => row.isChecked, this.onCheckboxClicked, { deep: true, immediate: true });
row.subRows?.forEach((subRow) => {
this.$watch(() => subRow.isChecked, this.onCheckboxClicked, { deep: true, immediate: true });
});
});
}
}
</script>
The Issue: Despite my efforts, the sumOfChecked method does not trigger when the isChecked property changes. It should be called whenever a checkbox is toggled, even within nested sub-rows.
My Attempts: I set up a deep watcher on rows to detect changes in isChecked properties. Integrated a recursive function inside sumOfChecked to compute the total of checked rows, including sub-rows. Ensured that the onCheckboxClicked method is triggered upon checkbox change. Unfortunately, the sumOfChecked method fails to activate as anticipated.
Query: How can I effectively monitor changes in the isChecked property of each row and its sub-rows to trigger the sumOfChecked method accordingly? Is there a more efficient approach to achieve this in Vue.js?