I use vue js version 2
My child component like this :
<template>
...
<div >
<b-input placeholder="Search" @input="(val) => searchChange(val)" />
</div>
...
</template>
<script>
export default {
props: [
"searchChange",
]
};
</script>
When search, it will call method in parent component
The parent component like this :
<template>
...
<page-heading
:searchChange="searchChange"
></page-heading>
...
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import PageHeading from "@/views/app/reports/PageHeading";
export default {
components: {
"page-heading": PageHeading,
},
methods: {
...mapActions(["getReports"]),
searchChange(val) {
this.search = val;
this.page = 1;
},
changePage(pageNum) {
this.page = pageNum;
},
},
computed: {
...mapGetters({
page: "reportPage",
search: "reportSearch",
}),
},
watch: {
search() {
this.page = 1;
},
},
mounted() {
this.getReports();
}
};
</script>
I use vuex store. It's like this :
import axios from 'axios'
const state = {
page: 1,
search: "",
}
const getters = {
reportSearch: state => state.search,
reportPage: state => state.page,
}
const mutations = {
getReportSuccess (state, res) {
state.total = res.data.length;
state.perPage = res.perPage;
},
}
const actions = {
getReports ({ commit }) {
axios
...
}
}
export default {
state,
getters,
mutations,
actions
}
When I try to search there exist error like this :
[Vue warn]: Computed property "page" was assigned to but it has no setter.
How can I solve this problem?
Please help. Thank you very much
CodePudding user response:
I see two things
- a mapped getter for page and search
...mapGetters({ page: "reportPage", search: "reportSearch", }),
- and a mutation of the getters
searchChange(val) { this.search = val; this.page = 1; },
vuex getters don't have setters, you have to invoke a mutation manually
to get around that, you need to invoke the vuex action to update the state
const mutations = {
getReportSuccess (state, res) {
state.total = res.data.length;
state.perPage = res.perPage;
},
setReportPage(state, page) {
state.reportPage = page;
},
setReportSearch(state, search) {
state.reportSearch = search;
},
}
const actions = {
getReports ({ commit }) {
axios
...
},
setPage({commit}, page) {
commit('setReportPage', page);
},
setSearch({commit}, search) {
commit('setReportSearch', search);
},
}
this will add the actions and mutations needed to update individually
then instead of these methods:
methods: {
...mapActions(["getReports"]),
searchChange(val) {
this.search = val;
this.page = 1;
},
changePage(pageNum) {
this.page = pageNum;
},
},
you would have
methods: {
...mapActions(["getReports", "setPage", "setSearch"]),
searchChange(val) {
this.setSearch(val);
this.setPage(1);
},
changePage(pageNum) {
this.setPage(pageNum);
},
},
and the watch can be
watch: {
search() {
this.setPage(1);
},
},
alternatively...
you could use a computed with a set and get like
computed: {
...mapGetters("reportPage","reportSearch"]),
page:
get: function () {
return this.reportPage;
},
set: function (value) {
this.setPage(value)
},
search:
// or if you don't map getters and actions ...
get: function () {
return this.$store.getter.reportSearch;
},
set: function (value) {
this.$store.commit("setSearch", value);
this.$store.commit("setPage", 1); // optional if you want to remove use of `searchChange`
},
},
this approach would allow you to map the v-model
<b-input placeholder="Search" v-model="search" />