Currently, I am in the process of developing a straightforward task management application using Vue and Electron. My framework is reliant on the electron-vue boilerplate with Vuex store integration. The app allows users to add new items to a list (and modify existing ones) through a modal interface. Once the user input is collected by the modal, it is forwarded to a store action which triggers a mutation to update the store data and append a new item to the list array.
The hierarchy goes as follows: LayerItem
is a child component of Layer
, which in turn is a child of LayerMap
. Data from the store is accessed within the parent LayerMap
component and passed down to children components via props.
To replicate the issue described: Create a new item using showEditItemDialog
feature in the Layer
component. As part of the SAVE_LAYER_ITEM
mutation process, a new ID is generated and assigned to the newly created item. Subsequently, the updated item is appended to the layer.items
array. Although the UI reflects this change and displays the correct item.text
, there seems to be a discrepancy in the displayed item.id
. A console.log
statement within the mutation logs an ID different from the one seen in the UI rendering of the LayerItem
component where <p>{{ item.id }}</p>
resides. Consequently, attempting to edit or update a recently added item results in a mutation creating a new item instead of updating the intended one, as the received ID cannot be located within the store array.
I understand that the details provided involve significant code snippets. However, I have made efforts to trim down unnecessary sections. In the example below, a new item "test" has been created, highlighting the disparity between the stored ID and the displayed ID.
Screenshot of Terminal logs https://i.sstatic.net/3sQ7k.png
Screenshot of DevTools console https://i.sstatic.net/k2tD4.png
Screenshot of Vue DevTools store https://i.sstatic.net/hcrOc.png
Screenshot of the UI https://i.sstatic.net/ozXJi.png
LayerMap.vue
// 'layers' is computed property fetching data from the store
<draggable
v-model="layers"
v-bind="getDragOptions"
>
<Layer v-for="(layer, index) in layers" :key="index" :layer="layer"></Layer>
</draggable>
<DetailsModal></DetailsModal>
// Inside computed
computed: {
layers() {
return this.$store.getters.allLayers
}
}
Layer.vue
// 'layer' being passed from parent as prop
<span primary-focus @click="showEditItemDialog">Add Item</span>
<draggable v-model="items" v-bind="dragOptions" class="items">
<LayerItem v-for="item in items" :item="item" :layer="layer" :key="item.id"></LayerItem>
</draggable>
// 'items' is a computed property
items: {
get() {
return this.layer.items
}
}
// Function handling 'Add Item' click event and emitting signal to be caught by DetailsModal.vue
methods: {
showEditItemDialog() {
let payload = {
layer: this.layer,
item: {
id: '',
text: ''
}
}
this.$bus.$emit('item-editing', payload)
}
}
LayerItem.vue
// Layer Item Component
<div class="layer-item" @click.prevent="startEditing">
<div class="item-body">
<p>{{ this.item.text }}</p>
<p>{{ item.id }}</p>
</div>
</div>
// Event triggered on click providing details of the clicked layer item
methods: {
startEditing() {
let payload = {
layer: this.layer,
item: {
id: this.item.id,
text: this.item.text
}
}
this.$bus.$emit('item-editing', payload)
}
}
}
DetailsModal.vue
// 'editLayerForm' stores the layer item id and text
<p>{{editLayerForm.id}}</p>
<div class="bx--form-item">
<input
type="text"
v-model="editLayerForm.text"
/>
</div>
// Within <script>, event is intercepted and handled; 'editLayerForm' gets updated with payload information
mounted() {
this.$bus.$on('item-editing', this.handleModalOpen)
},
methods: {
handleModalOpen(payload) {
this.layer = payload.layer
this.editLayerForm.id = payload.item.id
this.editLayerForm.text = payload.item.text
this.visible = true
console.log('editing', payload)
},
handleModalSave() {
let payload = {
layerId: this.layer.id,
item: {
id: this.editLayerForm.id,
text: this.editLayerForm.text
}
}
console.log('save', payload)
this.$store.dispatch('saveLayerItem', payload)
}
}
Store.js
const actions = {
saveLayerItem: ({ commit }, payload) => {
console.log('action item id', payload.item.id)
commit('SAVE_LAYER_ITEM', payload)
}
}
const mutations = {
SAVE_LAYER_ITEM: (state, payload) => {
let layer = state.map.layers.find(l => l.id === payload.layerId)
let itemIdx = layer.items.findIndex(item => item.id === payload.item.id)
console.log('mutation item id', payload.item.id)
if (itemIdx > -1) {
// For existing item
console.log('update item', payload.item)
Vue.set(layer.items, itemIdx, payload.item)
} else {
// For new item
payload.item.id = guid()
console.log('save new item', payload.item)
layer.items.push(payload.item)
}
}
}