I have a DocumentView.vue
component. This component has a DocumentListingView.Vue
component. The DocumentListingView.vue
has a DocumentItem.vue
componente. In the DocumentItem.vue
componente the respective document can be deleted (by api call). After deletion I want the DocumentListingView.vue
to be updated. That means that the child has to tell the parent, please update your DocumentListingView
by firing a new api call. I know that with $emit and pinia store you can implement the child - parent communication. But I just don't know how it should look architecturally.
Problem: I am trying to implement it with pinia. Unfortunately I don't know the last step, how to update the data in the listing.
Question: What is the theoretical concept? The child element should update the list of the ParentView?
Below you can see the files I use for this. They are reduced to the essential: DocumentView.vue
(Parent), DocumentListingView.vue
(child), DocumentItem.vue
(Grandchild), apiData.js
(pinia).
<script setup>
import { ref, computed as compi, onMounted } from 'vue'
import DocumentListing from './document/DocumentListingView.vue'
import { useApiDataStore } from '@/stores/apiData';
let list = {};
const apiData = useApiDataStore(); // init stores for api call
async function getDocumentList() {
await apiData.refreshDocumentList();
list = await apiData.listData;
}
getDocumentList();
</script>
<template>
<div>
<DocumentListing :documents="list"/>
</div>
</template>
<template>
<h2>Documents</h2>
<div class="documentListing">
<div v-for="item in documents">
<DocumentItem :data="item"></DocumentItem>
</div>
</div>
</template>
<script lang="ts" setup>
import DocumentItem from '../../components/DocumentItem.vue'
defineProps({
documents: Object,
})
</script>
<script setup>
import { useApiDataStore } from '@/stores/apiData';
defineProps({
data: Object,
});
const apiData = useApiDataStore();
const removeDocument = async (document) => {
// api call to remove document
apiData.refreshDocumentList();
}
</script>
<template>
<div>
<button @click="removeDocument(data)">Delete Doument></button>
</div>
</template>
import { defineStore } from 'pinia'
export const useApiDataStore = defineStore('apiData', {
id: 'apiData',
state: () => ({
listData: {}
}),
actions: {
async refreshDocumentList() {
const endpoint = "http://localhost:8888/api.php?list";
const response = await fetch(endpoint);
const json = await response.json();
this.listData = json;
}
}
})
You can solve this, when you will use in you DocumentView.vue the state property apiData.listData
instead of local list property. I commented the changes.
<script setup>
import { ref, computed as compi, onMounted } from 'vue'
import DocumentListing from './document/DocumentListingView.vue'
import { useApiDataStore } from '@/stores/apiData';
// let list = {}; //remove this line
const apiData = useApiDataStore(); // init stores for api call
async function getDocumentList() {
await apiData.refreshDocumentList();
// list = await apiData.listData; // remove this line
}
getDocumentList();
</script>
<template>
<div>
<DocumentListing :documents="apiData.listData"/> <!-- replace list with apiData.listData -->
</div>
</template>