I can do it actually using option API
, but now I'm using composition API
with composables
and I'm stuck. Have searched online all day but got no answer.
So, I have two components
(members.vue
and memberStore.vue
). My goal is when I post a new member in memberStore.vue
(which I load in members.vue
), the member list in that parent component should be automatically re-rendered.
here are those pages:
members.vue
<template>
<div>
<memberStore></memberStore>
<table >
<thead>
<tr>
<th><span>Name</span></th>
<th><span>Address</span></th>
<th ></th>
</tr>
</thead>
<tbody >
<template v-for="item in members" :key="item.id">
<tr>
<td> {{ item.name }} </td>
<td> {{ item.address }} </td>
</tr>
</template>
</tbody>
</table>
</div>
</template>
<script>
import useMembers from "../../composables/members";
import { onMounted } from "vue";
import memberStore from "../../components/members/memberStore.vue";
export default {
components: { memberStore },
setup() {
const { members, getMembers } = useMembers();
onMounted(getMembers);
return {
members,
};
},
};
</script>
memberStore.vue
<template>
<div>
<form @submit.prevent="saveMember">
<div>
<div><label for="name" >Name</label></div>
<div > <input type="text" name="name" id="name" v-model="form.name" > </div>
<div> <label for="address">Address</label > </div>
<div><input type="text" name="address" id="address" v-model="form.address" ></div>
</div>
<div>
<button type="submit" > Save</button>
</div>
</form>
</div>
</template>
<script>
import { reactive } from "vue";
import useMembers from "../../composables/members";
export default {
setup() {
const form = reactive({
name: "",
address: "",
});
const { errors, storeMember } = useMembers();
const saveMember = async () => {
await storeMember({ ...form });
};
return {
form,
errors,
saveMember,
};
},
};
</script>
src/composables/members.js
import { ref } from "vue";
import axios from "axios";
import { useRouter } from "vue-router";
import axiosClient from "../axios";
export default function useMembers() {
const members = ref([]);
const member = ref([]);
const router = useRouter();
const errors = ref("");
const getMembers = async () => {
let response = await axiosClient.get("/members");
members.value = response.data.data;
};
const getMember = async (id) => {
let response = await axiosClient.get("/members/" + id);
member.value = response.data.data;
};
const storeMember = async (data) => {
errors.value = "";
try {
await axiosClient.post("/members", data);
} catch (e) {
if (e.response.status === 422) {
errors.value = e.error.response.data;
}
}
};
return {
members,
getMembers,
router,
member,
getMember,
storeMember,
};
}
All of these are working as I expected. The only problem is I can't find a way to auto re-render the parent component
I solved it using emit event
In memberStore.vue
I added the following:
script
emits: ["customChange"],
setup(props, context) {
...
const handleChange = () => {
context.emit("customChange");
};
return {
....
handleChange,
};
}
trigger
<form @submit.prevent="saveMember" @submit="handleChange">
members.vue
<memberStore @customChange="getmembers"></memberStore>