Let's begin by discussing the layout. I have a page dedicated to showcasing information about a specific company, with a component Classification.vue
. This component displays categories of labels and the actual labels assigned to the current company. Initially, I fetch all possible categories using an axios get request, followed by retrieving all labels assigned to the current company. Then, I map the labels to their respective categories within the component Classification.vue
:
import DoughnutChart from "@comp/Charts/DoughnutChart";
import ModalDialog from '@comp/ModalDialog/ModalDialog';
const EditForm = () => import('./EditForm');
export default {
components: {
DoughnutChart, ModalDialog, EditForm
},
props: ['companyData'],
async created() {
const companyLabels = await this.$axios.get('/companies/' + this.companyData.id + '/labels');
const allLabelsCategories = await this.$axios.get('/labels/categories');
allLabelsCategories.data.map(cat => {
this.$set(this.labelsCategories, cat.labelCategoryId, {...cat});
this.$set(this.labelsCategories[cat.labelCategoryId], 'chosenLabels', []);
});
companyLabels.data.map(l => {
this.labelsCategories[l.label.labelCategory.labelCategoryId].chosenLabels.push({...l.label, percentage: l.percentage})
});
},
computed: {
portfolioChartData() {
let portfolios = [];
// 35 id stands for 'Portfolio' labels category
if (this.labelsCategories[35] !== undefined && this.labelsCategories[35].chosenLabels !== undefined) {
this.labelsCategories[35].chosenLabels.map(label => {
portfolios.push({label: label.name, value: label.percentage});
});
}
return portfolios;
},
portfolioLabels() {
let portfolios = [];
// 35 id stands for Portfolio labels category
if (this.labelsCategories[35] !== undefined && this.labelsCategories[35].chosenLabels !== undefined) {
return this.labelsCategories[35].chosenLabels;
}
return portfolios;
}
},
data() {
return {
labelsCategories: {}
}
}
}
Everything seems to be working smoothly so far. The object labelsCategories
contains keys that are category IDs and values that are category objects with the added key chosenLabels
, which we set up in the created()
method. Computed properties are utilized for the 'Portfolio' category chart. The use of $set in the created()
method triggers reactivity in the labelsCategories
object, allowing computed properties to react accordingly.
Now, a new component within Classification.vue
- EditForm.vue
is dynamically imported. In this component, a similar process is carried out, however, all possible labels for every category need to be retrieved, not just the assigned ones. To achieve this, a prop is passed as follows:
<modal-dialog :is-visible="isFormActive" @hideModal="isFormActive = false">
<EditForm v-if="isFormActive" ref="editForm" :labels-categories-prop="{...labelsCategories}" />
</modal-dialog>
The EditForm
component is structured like this:
export default {
name: "EditForm",
props: {
labelsCategoriesProp: {
type: Object,
required: true,
default: () => ({})
}
},
created() {
this.labelsCategories = Object.assign({}, this.labelsCategoriesProp);
},
async mounted() {
let labels = await this.$axios.get('/labels/list');
labels.data.map(label => {
if (this.labelsCategories[label.labelCategoryId].labels === undefined) {
this.$set(this.labelsCategories[label.labelCategoryId], 'labels', []);
}
this.labelsCategories[label.labelCategoryId].labels.push({...label});
});
},
data() {
return {
labelsCategories: {}
}
}
}
And now, the issue arises. Whenever the modal window containing the EditFrom
component is opened, the computed properties from Calssification.vue
are triggered causing the chart to animate and change its data. Why is this happening? After investigating further, it was discovered that the use of $set in the EditForm
component also impacts the parent component (Classification.vue
). How is this even possible? Despite attempting to pass the prop as {...labelsCategories} and using
this.labelsCategorie = Object.assign({}, this.labelsCategoriesProp);
, changes made in the child component affect the parent. A direct comparison between the prop and labelsCategories objects within the EditForm component through ===
and 'Object.is()' reveals they are not identical, leading to confusion on my end. Any assistance in resolving this matter would be greatly appreciated.
By the way, one workaround I found is passing the prop as :labels-categories-prop="JSON.parse(JSON.stringify(labelsCategories))"
, although it feels somewhat like a hack.