Vue Composition API for automatic fetch data when condition has been changed
I write backstage use Vuejs 2. After a period of time, I noticed i need write same code every time, like this page with many filters.
I add conditions, loading, results in data
data(){
return {
loading: false,
results: [],
conditions: {
name: '',
type: '',
// and more
}
}
}
Then watch the conditions changed to fetch data
watch: {
conditions: {
immediate: true,
handler: 'fetchData'
}
}
Before fetch data, i use computed to get query object and filter falsy value like '', null, []
computed: {
queryObject () {
// do something with this.conditions
return query
}
}
Update the uri before fetch data
this.$router.push('new path')
Okay, now doing fetch data
methods: {
fetchData () {
this.loading = true
//do something
api(this.queryObject).then(res=>{
this.results = res.data
}).finally(()=>{
this.loading = false
})
//do something
}
}
All done ! ...🤪 Wait ! I need handle user refresh page to sync query object value to conditions ....just keep fighting 😇
Until i used composition-api create vue-condition-watcher
prototype last year. It's really really save my time.
Now vue3 is going on beta, that's why i created this project. Can't wait vue3 release! Hope this project can help someone experiencing the same troubles.
- You can write less code in list data page with filters.
- Auto watch conditions changed to fetch new data.
- Auto filtter falsy value in conditions.
- Auto convert the corresponding type. (string, number, array, date)
- Sync the state with the query string and initialize off of that and that back/forward/refresh work.
Download example here (Use Vite)
$ cd examples/
$ yarn
$ yarn dev
Todo
- back/forward page sync query string
- add test for router
Simple example for vue-next
and vue-router-next
createApp({
template: `
<div class="filter">
<input type="checkbox" id="male" value="male" v-model="conditions.gender">
<label for="male">Male</label>
<input type="checkbox" id="female" value="female" v-model="conditions.gender">
<label for="female">Female</label>
<button @click="refresh">Refresh</button>
</div>
<div class="container" v-if="!loading && data">
<div class="card" v-for="item in data.results" :key="item.id.value">
<div>
<img :src="item.picture.thumbnail"/>
</div>
<h4>{{`${item.name.first} ${item.name.last}`}}</h4>
<div>{{item.email}}</div>
<div>{{item.phone}}</div>
</div>
</div>
<div class="loading" v-else>Loading...</div>
`,
setup() {
const config = {
fetcher: params => api.users(params),
conditions: {
gender: [],
},
}
return useConditionWatcher(config, {sync: 'router'})
},
})
.provide('router', router)
.use(router)
.mount(document.createElement('div'))
In your project
$ yarn add vue-condition-watcher
Or with npm
$ npm install vue-condition-watcher
const { conditions, data, error, loading, refresh } = useConditionWatcher(config, queryOptions)
-
config
: An object of config for vue-condition-watcher-
fetcher
(🚧Required) : A promise returning function to fetch data -
conditions
(🚧Required) : An object of conditions, also be initial value -
defaultParams
: An object of fetcher's default parameters -
beforeFetch
: A function you can do before fetch dataconst config = { fetcher: params => axios.get('url', { params }), defaultParams: { type: 'member' }, conditions: { offset: 0, limit: 10, username: '', tags: [], created_at: new Date() }, beforeFetch: conditions => { // conditions is an object clone copy from config.conditions conditions.created_at = dayjs(conditions.created_at, 'YYYY-MM-DD'); return conditions } }
queryOptions
work base on vue-router, you need install vue-router first. -
-
queryOptions
: An object of options to sync query string with conditions-
sync
: key of provide name ( String | Symbol ). main.js: register routerimport {createApp} from 'vue' import App from './App.vue' import { router } from './router' const app = createApp(App) .provide('router', router) // it's should be required .use(router) .mount('#app')
then
useConditionWatcher(config, {sync: 'router'})
-
ignore
: you can ignore key name from conditions, will not push with query.useConditionWatcher(config, {sync: 'router', ignore: ['offset', 'limit']})
-
-
reactive
: An object and returns a reactive proxy of conditions -
data
: Data resolved byconfig.fetcher
-
error
: Error thrown byconfig.fetcher
-
loading
: Request is loading -
refresh
: A function to re-fetch data