I store a couple thousands google maps markers in an API done with feathersjs. I use feathers-vuex on the frontend and I need to fetch all this data on created(). This is what I have so far, but it only fetches 10 items.
<script>
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
name: 'a-map',
computed: {
...mapGetters('plates', {
plates: 'list'
})
},
methods: {
...mapActions('plates', {
findPlates: 'find'
})
},
created() {
// Query plates from Feathers
this.findPlates();
}
}
</script>
You have pagination on your service which means (by default) only the first 10 items will show. You can either delete the pagination setting on your service, update it, or take advantage of the pagination by using $skip in subsequent requests.
Pagination documentation
There is a good explanation in the docs of feathers-Vuex. Look here:
hhttps://vuex.feathersjs.com/common-patterns.html#reactive-lists-with-live-queries
The issue is you have to read records from backend into Feather-vuex-store in created. With the getter in computed you get records from the feathers-Vuex store. The benefit of this is computed is synchronized with the backend, even if somebody add, mutate or delete records in the backend.
WMDTech is right, this is because of pagination in your backend. A simple fix is to do the following, but be wary of large datasets
Give this a try:
created() {
// Query plates from Feathers
this.findPlates( {
paginate: false
});
}
Related
This is a screenshot from another question about mapGetters
Link to the question I took the screen from
In Vue.js I saw an answer to a post.
It said :
In your Component
computed: {
...mapGetters({
nameFromStore: 'name'
}),
name: {
get(){
return this.nameFromStore
},
set(newName){
return newName
}
}
}
And I wonder why newName is a "new" name ? And also what it looks like to call the getter in the template html section. Do we use the nameFromStore like a data in the template ?
I tried to see how getters are used but what I found didn't look like this structure. The things I found looked like someone using a value in data that returns this.$store.getters.nameFromStore but I don't want to use the data and do it all in the computed instead like the picture I attached if someone can please help me ?
If you simply want to use mapGetters to access data store in vuex state you can do it as you have it above, without the get/set computed. I'm not sure what the intention of that get/set computed property was but it doesn't look like it would work as expected.
Try this:
// vuex index.js
// ...
getters: {
getAnimals: state => {
return state.items.filter(i => i.type === 'animal');
}
}
// your component.vue
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
...mapGetters(['getAnimals']) // access using this.getAnimals
// or
...mapGetters({ animals: 'getAnimals' }) // access using this.animals
}
}
The bennefit to using it this way is being a computed property, when the items change in vuex state, they will be recomputed, and your component will react to this change. Hopefully this is a clear explanation.
The vue docs:
https://vuex.vuejs.org/guide/getters.html#method-style-access
I realise this is a common issue with people new to vue and vuex, but I've been using it for two years now and thought I understood the ins and outs. Yet I'm stumped. There must be something I'm overlooking.
We've got a couple of complex models that used to have layouts hard-coded in the front end, and now some of those come from the backend instead, so I added a store module to handle that:
import { ActionTree } from 'vuex';
import { RootState } from '#/store';
import request from '../../services/request';
import layouts from '../../layouts';
export const types = {
FETCH_LAYOUT: `${MODULE_NAME}${FETCH_LAYOUT}`,
};
const initialState = {
layout: layouts,
};
const actions: ActionTree<LayoutState, RootState> = {
async [FETCH_LAYOUT]({ commit, state }, id) {
if (!state[id]) {
const layout = await request.get(`layout/${id}`);
commit(types.FETCH_LAYOUT, { layout, id });
}
},
};
const mutations = {
[types.FETCH_LAYOUT](state: any, { layout, id }) {
state.layout[id] = layout;
},
};
export default {
namespaced: true,
state: initialState,
getters: {},
actions,
mutations,
};
Everything here seems to work fine: the request goes out, response comes back, state is updated. I've verified that that works. I've got two components using this, one of them the parent of the other (and there's a lot of instances of the child). They're far to big to copy them here, but the import part is simply this:
computed: {
...mapState({
layout: (state: any) => {
console.log('mapState: ', state.layout, state.layout.layout[state.modelName]);
return state.layout.layout[state.modelName];
},
}),
},
This console.log doesn't trigger. Or actually it looks like it does trigger in the parent, but not in the children. If I change anything in the front-end code and it automatically loads those changes, the child components do have the correct layout, which makes sense because it's already in the store when the components are rerendered. But doing a reload of the page, they lose it again, because the components render before the layout returns, and they somehow don't update.
I'm baffled why this doesn't work, especially since it does seem to work in the parent. Both use mapState in the same way. Both instantiate the component with Vue.component(name, definition). I suppose I could pass the layout down as a parameter, but I'd rather not because it's global data, and I want to understand how this can fail. I've considered if maybe the state.layout[id] = layout might not trigger an automatic update, but it looks like it should, and the parent component does receive the update. I originally had state[id] = layout, which also didn't work.
Using Vue 2.6.11 and Vuex 3.3.0
According to the official vue.js documentation, component data must be a function.
In my situation, i want to get data with an axios call and store this data in a component.
The problem is, if a declare this data as a function as the documentation advice to, every time i will need this component it will do a new axios call.
My main goal using vue-components was to minimize axios calls by re-using components-data through my vues, to improve performance.
Am i wrong to use vue-components in this situation?
EDIT: here's some code to clarify my question:
What the documentation recommend to do (data is a function which returns data, which means it will do the axios call everytime you want to use the data i guess.):
Vue.component('user-infos', {
data() {
userInfos = axios.get('ajax/getInfosFiche.php?action=UserInformations')
}
});
What i did (data is an object, which means if multiple vues use it and one modify the data, it will be modified for all the vues) :
Vue.component('user-infos', {
data: {
userInfos = axios.get('ajax/getInfosFiche.php?action=UserInformations')
}
});
What you need is a data store, that holds your data and can be used from different components.
You could for example take a look at VueX.
Another way is to define your own custom store, which does not need to be as heavy as VueX.
One way to do this is create and export an observable object and import it from the components that need to have access to the store.
The way I am currently using it is by making the store object available through a global mixin. That way, every component has access to "this.$store" which holds my data.
const state = Vue.observable({ data: {} });
Vue.mixin({
computed: {
$store: {
get: function() {
return state.data;
},
set: function(newData) {
state.data = newData;
}
}
}
});
You can see the full example here.
Example Implementation
I've found it very difficult to find help online with this issue as no examples seem to match my use case. I'm basically wanting to check if I am on the right track in my approach.I have a single page Vue app:
Each row on the right is a component. On the left are listed three data sets that each possess values for the fields in the dashboard. I want it to be so that when you click on a dataset, each field updates for that set.
So if you click on 'Beds', the title becomes 'Beds' and all the fields populate the specific data for beds.
I want to do this without having separate pages for each dataset since that would seem to defeat the point of using a reactive framework like Vue. Only the embedded components should change, not the page.
I have installed Vue Router and have explored using slots and dynamic components but it is very hard to understand.
If someone experienced in Vue could just let me know the right broad approach to this I then know what I need to look into, at the moment it is difficult to know where to start. Thank you
You can use Vuex for that purpose.
Add property to the state, dataset for example. And mutation to change it. Every component on the right side should use that this.$store.state.dataset (or through mapState) for its own purposes. So when you're selecting one of listed datasets on the left side, it will mutate dataset in store with its own data.
Something like that:
store (there are alternate version, where we can use getter, but its little bit more complicated for just an example).
import Vue from 'vue';
const store = new Vuex.Store({
state: {
dataset: {}
},
mutations: {
setDataset(state, payload) {
Vue.set(state, 'dataset', payload);
}
}
});
one of the right side component
computed: {
dataset() {
return this.$store.state.dataset;
},
keywords() {
return this.dataset.keywords;
},
volume() {
return this.dataset.volume;
}
}
left menu
template:
{{dataset.title}}
code:
data() {
return {
datasets: [{
id: 1,
title: 'Sofas',
keywords: ['foo'],
volume: 124543
}]
}
},
methods: {
changeDataset(dataset) {
this.$store.commit('setDataset', dataset);
}
}
datasets is your data which you're loading from server.
BUT You can use some global variable for that, without Vuex. Maybe Vue observable, added in 2.6.
I have a list of todos that I'd like to watch and auto update when a change is made in a firebase backend
Got a bit stuck on what i hope is the last step (I am using nuxtjs for a SPA)
I have a getter in my vuex store as follows
getMyState: state => {
return state.todos
}
I am returning this getter to my component as follows
computed: {
...mapGetters(['getMyState'])
},
How do i now get my list to recognise when something has changed and update my array of results?
Thanks
Use watch property
watch: {
getMyState: function (new, old) {
}
},