I am trying to give the user certain permissions, but I am unable to access the teamsList object which shows empty in the 'if condition'
output console
please check this image. The if-condition is not working.
async created() {
console.log('teams list is before loading teams',this.teamsList);
this.loadTeams()
.then((response) => {
this.teamsList = response.data;
console.log('teams list is after loadteams',this.teamsList);
})
.catch((error) => {
console.log(error);
});
if (this.teamsList.teamName==='admins') {
this.haveAccess=true
console.log('access-check',this.teamsList.teamName);
}
console.log('access-check', this.haveAccess,this.teamsList);
}
An object's property can not be access directly if it is inside an array.
In your code, the teamsList variable is an array which is holding 3 items.
Therefore, you can not access the property teamName directly on that array.
If your data is dynamic then you need to loop on each time to access its property teamName.
this.teamsList.forEach(item => {
if (item.teamName === 'admins') {
this.haveAccess=true;
console.log('access-check', item.teamName);
}
})
If your data is fixed which means always an array of 3 items with fixed data then you can access it like this-
if (this.teamsList[0].teamName === 'admins') {
this.haveAccess=true;
console.log('access-check', this.teamsList[0].teamName);
}
Put if condition inside .then method, also you can remove async as you are not using await
created() {
console.log('teams list is before loading teams',this.teamsList);
this.loadTeams()
.then((response) => {
this.teamsList = response.data;
console.log('teams list is after loadteams',this.teamsList);
if (this.teamsList.teamName==='admins') {
this.haveAccess=true
console.log('access-check',this.teamsList.teamName);
}
console.log('access-check', this.haveAccess,this.teamsList);
})
.catch((error) => {
console.log(error);
});
}
As you might have any number of teams in a teamsList array. Hence, correct approach would be to add haveAccess property in each object and assign the true/false value against this property in each object.
Also, As teamsList is an array, you can access it's object properties by iterating it instead of direct access.
Your code should be like this :
created() {
this.loadTeams().then((response) => {
this.teamsList = response.data;
this.teamsList.forEach(team => {
team.haveAccess = (team.teamName === 'admins') ? true : false
})
}).catch((error) => {
console.log(error);
});
}
Related
I am struggling to learn implementing api in vue and filter the data but I can’t make it work.
This is code sandbox I created:
https://codesandbox.io/embed/agitated-architecture-91tj6?file=/src/components/HelloWorld.vue:943-971&codemirror=1
I am able to print the data but not to filter them even though I am using function for it.
If anyone can lead me in right path I would appreciate.
I saw your sandbox, here is how to make your code work:
methods: {
onChange() {
axios
.get("https://api.github.com/users")
.then((response) => {
this.results = response.data;
this.filterResults();
this.modal = true;
})
.catch((error) => {
console.log(error);
this.errors = true;
})
.finally(() => console.log("Data successfully loaded"));
},
filterResults() {
this.filteredResults = this.results.filter((result) => {
return result.login.toLowerCase().includes(this.search.toLowerCase());
});
},
.............
Explanation:
In your code, you write:
onChange() {
axios
.get("https://api.github.com/users")
.then((response) => {
this.filteredResults = response.data;
})
.catch((error) => {
console.log(error);
this.errors = true;
})
.finally(() => console.log("Data successfully loaded"));
this.filterResults();
this.modal = true;
},
You can see the position of this.filterResults(); is wrong. That is because you put the method outside of axios or calling api. The axios is asynchronous function, it means that it will wait for the data to be loaded, while method this.filterResults(); don't need to wait. This means that the method this.filterResults(); will be loaded before the axios function finished even if you put it in the order below the axios function, basically it means that you are calling this.filterResults(); function when the data is still empty. The solution to this is that by calling this.filterResults(); inside the axios function, you can put it in .then() if you want to use the successfully retrieved data.
The second problem in your code is in the filtering logic.
filterResults() {
this.filteredResults = this.results.filter((result) => {
return result.toLowerCase().includes(this.search.toLowerCase()) > -1;
});
},
From what I understand, you want to filter the result with the this.search data from the input. Here you are calling this.results, but when do you assign any value to the this.resuts? in the axios you assign the value to this.filteredResults = response.data; instead of this.results= response.data;, it means the variable this.results is empty. So you have to change this.filteredResults = response.data; to this.results = response.data; in axios.
Next is the logic in your filter
return result.toLowerCase().includes(this.search.toLowerCase()) > -1;
What you want to achieve is filtering the result.login with this.search value. But here you are filtering the result which as object type data with this.search value. Also, you don't need to put > -1 operation, because includes will return true or false.
My problem is that when I go from one user page to another user page the info in component still remains from first user. So if I go from /user/username1 to /user/username2 info remains from username1. How can I fix this ? This is my code:
UserProfile.vue
mounted() {
this.$store.dispatch('getUserProfile').then(data => {
if(data.success = true) {
this.username = data.user.username;
this.positive = data.user.positiverep;
this.negative = data.user.negativerep;
this.createdAt = data.user.createdAt;
this.lastLogin = data.user.lastLogin;
data.invites.forEach(element => {
this.invites.push(element);
});
}
});
},
And this is from actions.js file to get user:
const getUserProfile = async ({
commit
}) => {
try {
const response = await API.get('/user/' + router.currentRoute.params.username);
if (response.status === 200 && response.data.user) {
const data = {
success: true,
user: response.data.user,
invites: response.data.invites
}
return data;
} else {
return console.log('Something went wrong.');
}
} catch (error) {
console.log(error);
}
};
Should I add watch maybe instead of mounted to keep track of username change in url ?
You can use watch with the immediate property, you can then remove the code in mounted as the watch handler will be called instead.
watch: {
'$route.params.username': {
handler: function() {
this.$store.dispatch('getUserProfile').then(data => {
if(data.success = true) {
this.username = data.user.username;
this.positive = data.user.positiverep;
this.negative = data.user.negativerep;
this.createdAt = data.user.createdAt;
this.lastLogin = data.user.lastLogin;
data.invites.forEach(element => {
this.invites.push(element);
});
}
});
},
deep: true,
immediate: true,
},
}
Your page is loaded before the data is retrieved it seems, you need put a "loading" property in the data and have a v-if="!loading" for your component then it will only render once the display is updated. Personally I would avoid watch if I can it is not great for performance of for fine grained handling.
Yes you should add wach on statement that contain user info.(you may have a problem to watch on object, so you can save user info in json, but im not sure). When user changing - call action, after recived response call mutation that should change a state, then watch this state.
And you might use better syntax to receive data from store. That is really bad idea call dispatch directly from your mouted hook, use vuex documentation to make your code better.
I want to make an API call to the server to fetch the data and then display them in a component. I have a created() method which dispatches an action to my store, which, in turn, commits the mutation to udpate my store with the data I got from the server. I also have computed method where I simply call the getter which fetches the data from the store. The code looks like this:
state
state: {
data: {
rides: []
}
}
component.vue
created() {
this.$store.dispatch('fetchUserRides');
}
computed: {
...mapGetters([
'userRides'
]),
}
store.js
//actions
fetchUserRides({ commit }) {
axios.get('/api/stats/current_week')
.then(response => {
commit('fetchUserRides', response)
})
.catch(error => {
commit('serverResponsError')
})
//mutations...
fetchUserRides(state, payload){
let rides = payload.data
rides.forEach((item) => {
state.data.rides.push(item)
})
//getters
userRides: state => {
let rides = state.data.rides
rides.sort(( a, b) => {
return new Date(a.date) - new Date(b.date);
});
return rides
}
I receive over 40 objects in the response, I did check it by console.log(state.data.rides) and they are there in 100%.
My problem is that when I log off and log back in again it throws an error "TypeError: Cannot read property 'sort' of null". But if I hit Refresh they appear fine. The login action redirects me to the page where I render this component. This looks like the computed property first tries to fetch data by the getter from the array before it is actually populated in the store. How can I make sure I get the array of objects in my component?
You probably need to set an empty array ([]) as an initial value to state.data.rides instead of null.
Another option will be to check that rides is truthy in your getters.
Something like:
if (rides) {
rides.sort(( a, b) => {
return new Date(a.date) - new Date(b.date);
});
}
return []
I was able to resolve my problem and it turns out I made a mistake. I completely forgot I set state.data.rides = null instead of an empty array state.data.rides = null, which would explain why the array was empty. It was a legacy code I had :)
Using axios to fetch api data:
fetchData () {
axios.get(globalConfig.OFFERS_URL)
.then((resp) => {
this.offersData = resp.data
console.log(resp)
})
.catch((err) => {
console.log(err)
})
}
Data function:
data () {
return {
offersData: {}
}
}
Now i can use fetched data in my template, like so: {{ offersData.item[0].id }}
But can i set the fetched data in a data function:
data () {
return {
offersData: {},
id: this.offersData.item[0].id
}
}
It's not working for me, is that even possible to store axios get's response in a data function?
You probably are looking for computed property:
data () {
return {
offersData: {},
}
},
computed() {
id() {
return this.offersData.item && this.offersData.item[0].id;
}
}
As for data function, it is used to define shape of state (set up the properties to be tracked) of component and give valid initial values to it. In this case, however, id should neither be a part of state (it's always a part of offersData value, after all) nor its initial value can be calculated before offersData is set up by a remote call.
I would like to return a single record from my back end using a Vuex store module in Nuxt.
I have the following in my component, which passes the value i want
( which is the $route.params.caseId )
created () {
this.$store.dispatch('cases/getCase', $route.params.caseId );
},
I pass the $route.params.caseId into my getCase action in my vuex store module as follows
getCase ({ commit, context }, data) {
return axios.get('http' + data + '.json')
.then(res => {
const convertcase = []
for (const key in res.data) {
convertcase.push({ ...res.data[key], id: key })
}
//console.log(res.data) returns my record from firebase (doesnt display the key though in the array, just the fields within the firebase record, but assume this is expected?
commit('GET_CASE', convertcase)
})
.catch(e => context.error(e));
},
the convert case is to extract the id from firebase key and add it to my array as id field (Is this correct for a single result from firebase in this way?)
My mutation
// Get Investigation
GET_CASE(state, caseId) {
state.caseId = caseId;
},
Now when I use Case Name: {{ caseId.case_name }} I'm not getting any result,
I'm not getting an error though, any thoughts on what i am doing wrong please
Many Thank
You can pass more data to an action like you did in the dispatch method and later access them normally.
Note the data parameter of the getCase function, in your example data === $route.params.caseId
//Load single investigation
getCase ({ commit, context }, data) {
return axios.get('http' + investigationID + '.json')
.then(res => {
const convertcase = []
for (const key in res.data) {
convertcase.push({ ...res.data[key], id: key })
}
commit('GET_CASE', convertcase)
})
.catch(e => context.error(e));
},
In case you want to use promises, check out the exemple below of a action in my app that fetches a single BLOG_POST
let FETCH_BLOG_POST = ({commit, state}, { slug }) => {
return new Promise((resolve, reject) => {
fetchBlogPost(slug, state.axios)
.then((post) => {
console.log("FETCH_BLOG_POSTS", post.data.data)
commit('SET_BLOG_POST', post.data.data)
resolve(post.data)
})
.catch((error) => {
console.log("FETCH_BLOG_POST.catch")
reject(error)
})
});
}