Vue data not updated in created() - javascript

I'm trying to transform an API response into a more useful form for building two tables. When I add debugging outputs inside my function in created(), I can see the desired output, but examining the data after the fact, it seems to have not changed. I suspect that something weird is happening with this, but I can't seem to sort it out.
Here's what I have so far:
export default {
name: 'component',
data: function() {
return {
tableOne: [],
}
},
computed: {
...mapState([
'modal'
])
},
created() {
api.get_appointments()
.then(appointments => {
for (var i = 0; i < appointments.length; i++) {
this.tableOne.push(
{
tech: appointments[i].tech_name,
date: appointments[i].scheduled_date
}
)
}
});
},
};
api.get_appointments() includes the following:
get_appointments() {
return axios({
method: "get",
url: '/appointments'
})
.then(res => (res.data.data))
.catch(error => {return error});
};

Since it's doing a request hit..the second console prints before the request is resolved. Try using async-await
async created() {
await api.get_appointments()
.then(appointments => {
for (var i = 0; i < appointments.length; i++) {
this.tableOne.push(
{
tech: appointments[i].tech_name,
date: appointments[i].scheduled_date
}
)
}
// console.log(this.tableOne);
});
// console.log(this.tableOne);
},

Related

Pinia|Vue3 I can't access the property of the object that returned from the Pinia action

first of all I am using the Mockjs to simulate the backend data:
{
url: "/mockApi/system",
method: "get",
timeout: 500,
statusCode: 200,
response: { //
status: 200,
message: 'ok',
data: {
'onlineStatus|3': [{
'statusId': '#integer(1,3)',
'onlineStatusText': '#ctitle(3)',
'onlineStatusIcon': Random.image('20*20'),
'createTime': '#datetime'
}],
'websiteInfo': [{
'id|+1': 1,
}]
}
}
}
the data structure would be: https://imgur.com/a/7FqvVTK
and I retrieve this mock data in Pinia store:
import axios from "axios"
import { defineStore } from "pinia"
export const useSystem = defineStore('System', {
state: () => {
return {
systemConfig: {
onlineStatus: [],
},
}
},
actions: {
getSystemConfig() {
const axiosInstance = axios.interceptors.request.use(function (config) {
// Do something before request is sent
config.baseURL = '/mockApi'
return config
}, function (error) {
// Do something with request error
return Promise.reject(error);
})
axios.get('/system/').then(res => {
this.systemConfig.onlineStatus = res.data.data.onlineStatus
})
// console.log(res.data.data.onlineStatus)
axios.interceptors.request.eject(axiosInstance)
}
}
})
I use this store in the parent component Profile.vue:
export default {
setup() {
const systemConfigStore = useSystem()
systemConfigStore.getSystemConfig()
const { systemConfig } = storeToRefs(systemConfigStore)
return {
systemConfig,
}
},
computed: {
getUserOnlineStatusIndex() {
return this.userData.onlineStatus//this would be 1-3 int.
},
getUserOnlineStatus() {
return this.systemConfig.onlineStatus
},
showUserOnlineStatusText() {
return this.getUserOnlineStatus[this.getUserOnlineStatusIndex - 1]
},
},
components: {UserOnlineStatus }
}
template in Profile.vue I import the child component userOnlineStatus.vue
<UserOnlineStatus :userCurrentOnlineStatus="userData.onlineStatus">
{{ showUserOnlineStatusText }}
</UserOnlineStatus>
here is what I have got https://imgur.com/fq33uL8
but I only want to get the onlineStatusText property of the returned object, so I change the computed code in the parent component Profile.vue:
export default {
setup() {
const systemConfigStore = useSystem()
systemConfigStore.getSystemConfig()
const { systemConfig } = storeToRefs(systemConfigStore)
return {
systemConfig,
}
},
computed: {
getUserOnlineStatusIndex() {
return this.userData.onlineStatus//this would be 1-3 int.
},
getUserOnlineStatus() {
return this.systemConfig.onlineStatus
},
showUserOnlineStatusText() {
return this.getUserOnlineStatus[this.getUserOnlineStatusIndex - 1]['onlineStatusText']//đź‘€I chage it here!
},
},
components: {UserOnlineStatus }
}
but I will get the error in the console and it doesn't work:
https://imgur.com/Gb68Slk
what should I do if I just want to display the specific propery of the retrived data?
I am out of my wits...
I have tried move the store function to the child components, but get the same result.
and I google this issue for two days, nothing found.
Maybe it's because of I was trying to read the value that the Profile.vue hasn't retrieved yet?
in this case, how could I make sure that I have got all the value ready before the page rendered in vue3? Or can I watch this specific property changed, then go on rendering the page?
every UX that has data is coming from remote source (async data) should has spinner or skeleton.
you can use the optional chaining for safe access (if no time to await):
return this.getUserOnlineStatus?.[this.getUserOnlineStatusIndex - 1]?.['onlineStatusText']

How does if else works?

I'm trying to figure out where my problem comes from in my algorithm.
I am trying to give the information about the connection status of a data sender with its data table.
I have translated it like this:
if new data is received ( new_id different from id_from_last_request) then I set the connection status to "connected" otherwise I set it to "disconnected"
<script>
export default {
data() {
return {
search: '',
tag_id: ['bts_d02c2b7d9098aaa2', 'bts_c077ffaa9098aaa2'],
headers: [
{
text: 'Tags',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'wifi', value: 'wifi' },
],
val_ia: 0,
desserts: [],
id_memory: [],
}
},
mounted() {
this.CreateTable();
setInterval(this.getDatafor, 1000)
},
methods: {
CreateTable() {
for (let i = 0; i < this.tag_id.length; i++) {
this.desserts.push(
{
name: this.tag_id[i],
},
)
}
},
async getDatafor() {
for (let i = 0; i < this.desserts.length; i++) {
this.val_ia = i;
await Promise.all([this.getAllData()]);
}
},
async getAllData() {
const tag_id_name = encodeURIComponent(this.tag_id[this.val_ia]);
const url = this.$api.getRESTApiUri() + `/all/last_id/${tag_id_name}`;
return fetch(url)
.then(res => res.text())
.then((result) => {
console.log(tag_id_name)
console.log(this.id_memory[this.val_ia]);
console.log(data[0].id)
const b = this.Test(this.id_memory[this.val_ia], data[0].id);
console.log(b)
if(b){
this.desserts[this.val_ia].wifi = 'connecté'
console.log('connecté')
}else{
this.desserts[this.val_ia].wifi = 'déconnecté'
console.log('déconnecté')
}
this.id_memory[this.val_ia] = data[0].id
})
.catch((error) => {
console.log(error)
});
},
Test(x, y) {
const a = x !== y
return a
},
}
}
</script>
Only in case I have no new data
const b = false
here is my console:
I should have the disconnected status only it shows me the connected status
There should be a logical explanation to it but I can't see it..
You are using equality without type coersion (x !== y) in your Test method.
Probably this.id_memory[this.val_ia] and data[0].id have different types - one is number, second one is string or otherwise.
The best solution is to convert those values to the same type before comparing like so:
Test(x,y){
return String(x) !== String(y)
}
Some use cases:
'123' === 123 // false
'123' == 123 // true
When creating my table, I forgot to push variables wifi and bluetooth so they did not update themselves.
CreateTable(){
for(let i = 0; i < this.tag_id.length; i++){
this.desserts.push(
{
name: this.tag_id[i],
wifi: 'déconnecté',
bluetooth: 0,
tension: 0,
courant: 0,
temperature: 0,
acceléromètre: 0,
pression_sys: 0,
pression_dias: 0,
frequence_cardiaque: 0,
taux_oxygène: 0,
},
)
}
},

apollo client offsetLimitPagination not working

I have a hook..
export function useLazyProposalList() {
const [getQueueData, { loading, data, error, fetchMore }] = useLazyQuery(PROPOSAL_LIST, {
fetchPolicy: 'no-cache',
});
const proposalList = React.useMemo(() => {
if (!data) {
return null;
}
return transformProposals(data);
}, [data]);
return {
getQueueData,
fetchMore,
loading,
data: proposalList,
error,
};
}
In the component
const {
getQueueData,
data: queueData,
fetchMore: fetchMoreProposals,
// loadMore: loadMore,
} = useLazyProposalList();
If user clicks on fetch more button, I call: fetchMoreProposals .
await fetchMoreProposals({
variables: {
offset: visibleProposalList.length,
},
});
but this doesn't update my data. I read that we should use offsetLimitPagination, but my data from query is not array itself. It's like this: queue { id: '1', items:[] } and because of this, offsetLimitPagination doesn't work. So I tried merge
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
queue: {
keyArgs: false,
merge(existing, incoming) {
console.log(existing, incoming);
if (!incoming) return existing;
if (!existing) return incoming;
},
},
},
},
}
but in the console, it just prints refs instead of real data.
What could be the issue ?

Vuejs2 - How to compare elements in two array with computed properties?

I'm working on a computed function for comparing two arrays... one keywords in data and another returned by computed keywords_list. When computed compare, he doesn't take in count values getting before by Axios in the first array ...
I don't know what to do ...
my code:
{
beforeCreate() {
this.$axios({
method: 'get',
url: '/api/rest/alerts/'
}).then(response => {
if ((response.data.keywords.length == 0) && (response.data.countries.length == 0)) {
this.alertEmpty = 'Aucune alerte de créée'
} else {
this.alert = response.data
this.keywords = response.data.keywords
this.countriesKeywords = response.data.countries
this.allSectorsSelected = response.data.all_sectors
}
})
},
data() {
return {
categories: "",
alert: '',
alertEmpty: '',
countriesKeywords: [],
countrySelected: '',
keywords: [],
update: false,
sectorSelected: "",
alerts: [],
keywordSelected: "",
errorKeyword: '',
successModification: '',
allSectorsSelected: null,
};
},
computed: {
keywords_list: function() {
for (var i = 0; i < this.sectors.length; i++) {
if (this.sectors[i].id == this.sectorSelected) {
return this.sectors[i].keywords;
}
}
},
allKeywordsInSector: function() {
if (this.keywords_list.every(item => this.keywords.indexOf(item) >= 0)) {
return true;
}
return false;
},
}
}
thanks for your help
very little information and it is unclear how the api result affects your computed values
The only thing i can say, properties in Vue doesn't reactive. So if sections isn't static, computed property sectorSelected will change only if sectorSelected changes
https://v2.vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow

Vue js Laravel - Axios making Multiple ( 2 ) Requests when changing pages , Category and Subcategory

I'm building an application with Vue on the frontend and Laravel PHP on the backend. Its a single page app (SPA).
When changing pages, sometimes - not always - axios makes two requests for the same page. I'm having trouble figure it out what is happening.
When the link changes I have two watchers, one for the top category and another for the sub-category. They trigger the created () hook that calls the loadData method.
If I change the main category and sub category ( Example: from 1/5 to 2/31 ), the loadData method is called two time. How can I fix this ?
Google Network Tab (The .json request does not represent the same type of page that I'm referring above, only the numbers ) :
<script>
import axios from 'axios'
import { mapGetters } from 'vuex'
import Form from 'vform'
export default {
data() {
return {
products: {
cat : {} ,
products : []
},
productsShow: '',
quickSearchQuery: '',
loadeddata : false,
}
},
methods: {
loadMore () {
this.productsShow += 21
},
loadData () {
if ( this.$route.params.sub_id ) {
axios.get('/api/cat/' + this.$route.params.cat_id + '/' + this.$route.params.sub_id).then(response => {
this.products = response.data
this.productsShow = 21
this.loadeddata = true
}).catch(error => {
if (error.response.status === 404) {
this.$router.push('/404');
}
});
} else {
axios.get('/api/cat/' + this.$route.params.cat_id ).then(response => {
this.products = response.data
this.productsShow = 21
this.loadeddata = true
}).catch(error => {
if (error.response.status === 404) {
this.$router.push('/404');
}
});
}
},
computed: {
...mapGetters({locale: 'lang/locale', locales: 'lang/locales' , user: 'auth/user'}),
filteredRecords () {
let data = this.products.products
data = data.filter( ( row ) => {
return Object.keys( row ).some( ( key ) => {
return String( row[key] ).toLowerCase().indexOf(this.quickSearchQuery.toLowerCase()) > -1
})
})
return data
}
},
created() {
this.loadData()
},
watch: {
'$route.params.cat_id': function (cat_id) {
this.quickSearchQuery = ''
this.loadData()
},
'$route.params.sub_id': function (sub_id) {
this.quickSearchQuery = ''
this.loadData()
}
}
}
</script>
So I see that you figured the issue by yourself.
To fix that, you can delay the loadData function (kind of debounce on the tail) so if it's being called multiple times in less than X (300ms?) then only the last execution will run.
try:
loadData () {
clearTimeout(this.loadDataTimeout);
this.loadDataTimeout = setTimeout(()=> {
//The rest of the loadData function should be placed here
},300);
}
Resolved :
watch: {
'$route.params': function (cat_id, sub_id) {
this.quickSearchQuery = ''
this.loadData()
},

Categories

Resources