I'm using vue-js and i encountered this problem where i call a get all api and then store it in an array. The logic works perfectly fine in the first component, however when i copied literally the exact same code and pasted it in a second component the call for some reason returns an empty array instead of the array of users. Here is the component
import UsersInServiceCenterService from "../services/UsersInServiceCenterService";
import UserService from "../services/UserService";
export default {
name: "service center",
data() {
return {
currentServiceCenter: null,
message: '',
listOfSpecificServiceCenter1: [],
listOfSpecifiedUsers1: [],
id:"",
};
},
methods: {
getServiceCenter(id) {
ServiceCenterService.get(id)
.then((response) => {
this.currentServiceCenter = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
updateServiceCenter() {
ServiceCenterService.update(this.currentServiceCenter.id, this.currentServiceCenter)
.then((response) => {
console.log(response.data);
this.message = "The service center was updated successfully!";
})
.catch((e) => {
console.log(e);
});
},
deleteServiceCenter() {
ServiceCenterService.delete(this.currentServiceCenter.id)
.then((response) => {
console.log(response.data);
this.$router.push({ name: "service centers" });
})
.catch((e) => {
console.log(e);
});
},
retrieveAllUsersByServiceCenterId(currentServiceCenter){
UsersInServiceCenterService.getAllUsersByServiceCenterId(currentServiceCenter.id)
.then((response) => {
this.listOfSpecificServiceCenter1 = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
retrieve(){
this.retrieveAllUsersByServiceCenterId(this.currentServiceCenter);
if(this.listOfSpecificServiceCenter1.length!=0){
for(var i =0 ; i<this.listOfSpecificServiceCenter1.length;i++){
UserService.get(this.listOfSpecificServiceCenter1[i].userId)
.then((response) => {
this.listOfSpecifiedUsers1.push(response.data);
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
}
}
this.isEmpty = !this.isEmpty;
},
},
mounted() {
this.message = "";
this.getServiceCenter(this.$route.params.id);
},
};
</script>
getServiceCenter(id) works fine and it returns the service center. However both of the retrieve() and the retrieveAllUsersByServiceCenterId(currentServiceCenter) do not work at all and they return the empty array. Here is the first component which works totally fine with literally the exact same functions.
import UserService from "../services/UserService";
import UsersInServiceCenterService from "../services/UsersInServiceCenterService";
export default {
name: "servicecenters-list",
data() {
return {
serviceCenters: [],
users:[],
currentServiceCenter: null,
currentUser: null,
currentIndex: -1,
currentUserIndex: -1,
id: "",
searchValue: "",
isEmpty: false,
rows: [],
listOfSpecificServiceCenter:[],
listOfSpecifiedUsers:[],
};
},
methods: {
retrieveServiceCenters() {
ServiceCenterService.getAllServiceCenters()
.then((response) => {
this.serviceCenters = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
retrieveUsers() {
UserService.getAllUsers()
.then((response) => {
this.users = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
refreshList() {
this.retrieveServiceCenters();
//this.retrieveUsers();
this.currentServiceCenter = null;
this.currentIndex = -1;
//this.currentUser = null;
//this.currentUserIndex = -1;
},
setActiveServiceCenter(servicecenter, index) {
this.currentServiceCenter = servicecenter;
this.currentIndex = index;
},
setActiveUser(user,userIndex){
this.currentUser= user;
this.currentUserIndex = userIndex;
},
// showList(currentServiceCenter){
// for(var i =0;i<currentServiceCenter.users.length;i++){
// }
// },
retrieve(){
this.retrieveAllUsersByServiceCenterId(this.currentServiceCenter);
if(this.listOfSpecificServiceCenter.length!=0){
for(var i =0 ; i<this.listOfSpecificServiceCenter.length;i++){
UserService.get(this.listOfSpecificServiceCenter[i].userId)
.then((response) => {
this.listOfSpecifiedUsers.push(response.data);
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
}
}
this.isEmpty = !this.isEmpty;
},
retrieveAllUsersByServiceCenterId(currentServiceCenter){
UsersInServiceCenterService.getAllUsersByServiceCenterId(currentServiceCenter.id)
.then((response) => {
this.listOfSpecificServiceCenter = response.data;
console.log(response.data);
})
.catch((e) => {
console.log(e);
});
},
addUserToServiceCenter(currentServiceCenter, currentUser) {
var data = {
serviceCenterId: parseInt(this.currentServiceCenter.id),
userId: parseInt(this.currentUser.id),
};
UsersInServiceCenterService.add(data)
.then((response) => {
//this.currentServiceCenter.id = response.data.id; //take care here
console.log(response.data);
this.submitted = true;
})
.catch((e) => {
console.log(e);
});
this.show=false
if(currentServiceCenter.users == Array.isArray(currentServiceCenter.users))
//currentServiceCenter.users = Array.isArray(currentServiceCenters.users) : [...currentServiceCenter.users, currentUser] : [currentUser]
currentServiceCenter.users.push(currentUser);
else{
currentServiceCenter.users = []
currentServiceCenter.users.push(currentUser);
}
},
removeAllServiceCenters() {
ServiceCenterService.deleteAllServiceCenters()
.then((response) => {
console.log(response.data);
this.refreshList();
})
.catch((e) => {
console.log(e);
});
},
searchId(id) {
ServiceCenterService.get(id)
.then((response) => {
this.currentServiceCenter = response.data;
})
.catch((e) => {
console.log(e);
});
this.refreshList();
// if(typeof id ==='string'){
// }
// else if(typeof id==='number'){
// CompanyService.get(id).then(response =>{
// this.currentCompany=response.data
// })
// .catch(e=>{
// console.log(e);
// });
// }
},
},
mounted() {
this.retrieveServiceCenters();
this.retrieveUsers();
},
computed:{
usersFilteredListByName(){
if(this.searchValue.trim().length >0){
return this.serviceCenters.filter((servicecenter) =>servicecenter.name.toLowerCase().includes(this.searchValue.trim()))
}
// if(this.searchValue.length>0 && isNaN(parseInt(this.searchValue))){
// return this.companies.filter((company) =>company.id.includes(this.searchValue))
// }
return this.serviceCenters
},
usersFilteredListById(){
if(this.searchValue.trim().length >0){
return this.serviceCenters.filter((servicecenter) =>servicecenter.id.toString().includes(this.searchValue))
}
return this.serviceCenters
},
}
};
</script>
You can ignore the rest of the functions and focus on the retrieve() and retrieveAllUsersByServiceCenterId(). Any help would be highly appreciated.
Related
I use two functions to load some components for my page and save it in two fields representatives and allUsers. Then I try to use additional func subtractSets() to a little bit modify loaded data. My problem is that fields this.representatives and this.allUsers in this adittional function are still not initialized. What I can do to get loaded data in subtractSets()?
setup() {
const representatives = ref([])
const allUsers = ref([])
data() {
return {
representatives,
users
}
}
},
methods(): {
loadUsersRepresentatives() {
axios.get('getRepresentatives').then(res => {
this.representatives = res.data
}).catch(() => {
...
})
});
},
loadAllUsers() {
axios.get('/getAllUsers').then(res => {
this.allUsers = res.data
}).catch(() => {
...
})
});
},
subtractSets(obj1, obj2) {
...
},
showRepresentativesDialog(facultyID) {
this.loadUsersRepresentatives(facultyID)
this.loadAllUsers()
this.subtractSets(this.representatives, this.allUsers)
this.representativesDialog = true
}
},
ยดยดยด
You are missing async / await
methods(): {
async loadUsersRepresentatives() {
return axios.get('getRepresentatives').then(res => {
this.representatives = res.data
}).catch(() => {
...
})
});
},
async loadAllUsers() {
return axios.get('/getAllUsers').then(res => {
this.allUsers = res.data
}).catch(() => {
...
})
});
},
subtractSets(obj1, obj2) {
...
},
async showRepresentativesDialog(facultyID) {
await this.loadUsersRepresentatives(facultyID)
await this.loadAllUsers()
this.subtractSets(this.representatives, this.allUsers)
this.representativesDialog = true
}
},
I've got a nativescript vue application, and on a certain page I need to fetch some data (every 3 seconds) from an api using axios. The data is returned in xml, and I convert it to json using xml2js. I'm using async/await for both these functions. Something is blocking the UI thread, because whenever this function runs scrolling in my app freezes, along with any animations.
Does anyone know what here is blocking the DOM?
<template>
//ui code here
</template>
<script>
import { mapGetters } from 'vuex'
import axios from 'axios'
import xml2js from 'nativescript-xml2js'
export default {
name: 'component1',
data () {
return {
pending: true,
error: false,
results: null,
refreshInterval: null
}
},
computed: {
...mapGetters({
token: 'main/token'
})
},
methods: {
async requestData() {
const headers = {
Cookie: 'USER_ID=' + this.token
}
const url = 'url goes here'
const parser = new xml2js.Parser({
async: true
})
try {
const response = await axios.get(url, { headers: headers })
const newData = await new Promise((resolve, reject) => parser.parseString(response.data, (err, result) => {
if (err) reject(err)
else resolve(result)
}))
this.results = newData['results']
this.error = false
this.pending = false
} catch (e) {
this.data = null
this.error = e
this.pending = false
}
this.pending = false
}
},
created() {
setTimeout(() => {
this.requestData()
},500)
this.refreshInterval = setInterval(() => {
this.requestData()
},3000)
},
beforeDestroy () {
clearInterval(this.refreshInterval)
}
}
</script>
EDIT:
I tried implementing workers to offload xml2js to another thread, but still having the same issue. This is how my code looks now:
home.vue:
<template>
<template/>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'component1',
data () {
return {
dataLoaded: true,
error: false,
results: null,
refreshInterval: null
}
},
computed: {
...mapGetters({
token: 'main/token'
})
},
methods: {
requestData() {
console.log('fetching....')
this.$backendService
.api()
.then(xml => {
return this.$backendService.x2jworker(xml)
})
.then(json => {
if( this.results !== json['results'] ) {
this.results = json['results']
}
this.dataLoaded = true
this.error = false
})
.catch((error) => {
this.dataLoaded = true
this.error = true
})
}
},
created() {
setTimeout(() => {
this.requestData()
},500)
this.refreshInterval = setInterval(() => {
this.requestData()
},3000)
},
beforeDestroy () {
clearInterval(this.refreshInterval)
}
}
</script>
backend-service.js:
import axios from 'axios';
import xml2js from 'nativescript-xml2js'
import { WorkerService } from "../worker.service"
export default class BackendService {
api() {
return new Promise((resolve, reject) => {
const url = 'url'
axios.get(url)
.then(response => {
resolve(response.data)
})
.catch((error) => {
if (error) {
console.log('uh oh')
reject(error)
}
})
})
}
x2jworker(xml) {
return new Promise((resolve, reject) => {
var workerService = new WorkerService()
var jsWorker = workerService.initJsWorker()
jsWorker.onmessage = m => {
resolve(m.data)
}
jsWorker.postMessage(xml)
jsWorker.onerror = e => {
console.log(e)
jsWorker.terminate()
reject(e)
}
})
}
}
worker/javascript.worker.js:
import 'tns-core-modules/globals'
import xml2js from 'nativescript-xml2js'
global.onmessage = function (msg) {
console.log("Inside JS worker...")
var parser = new xml2js.Parser({
async: true
})
parser.parseString(msg.data, function (err, result) {
if (err) {
console.log(err)
global.close()
} else {
global.postMessage(result)
}
})
}
worker-service.js:
const workers = []
export class WorkerService {
constructor() {
}
initJsWorker() {
if (this.jsWorker) {
return this.jsWorker
}
const JsWorker = require("nativescript-worker-loader!./workers/javascript.worker.js")
this.jsWorker = new JsWorker()
workers.push(this.jsWorker)
return this.jsWorker
}
}
if ((module).hot) {
(module).hot.dispose(() => {
workers.forEach(w => {
w.terminate()
})
})
}
its not waiting for validation and just run the else part :| where is my mistake?
async validateBeforeSubmit(event) {
await this.$validator.validateAll().then( result => {
if (result) {
console.log(result); // just log the -> true
// go submit
}else{
console.log(result); // just log the -> false
event.preventDefault();
var elmnt = document.getElementById("drop_zone");
elmnt.scrollIntoView();
}
})
.catch(error=>console.log(error));
},
i'm using veevalidator and i define some custom rules that need afew seconds to resolve:
created() {
this.$validator.extend('unique', {
// getMessage: field => 'At least one ' + field + ' needs to be checked.',
async validate(value, arg) {
arg = arg[0];
let sw = false;
if (arg == 'n_code') {
let data = {
'n_code': value
}
await Axios.post(duplicate_ncode, data, {
headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }
})
.then((response) => {
if (response.data == true) {
sw = true;
}
})
.catch(error => console.log(error));
if (sw) {
return true;
} else {
return false;
}
}
if (arg == 'email') {
let data = {
'email': value
}
await Axios.post(duplicate_email, data, {
headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }
})
.then((response) => {
if (response.data == true) {
sw = true;
}
})
.catch(error => console.log(error));
if (sw) {
return true;
} else {
return false;
}
}
if (arg == 'mobile') {
let data = {
'mobile': value
}
await Axios.post(duplicate_mobile, data, {
headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }
})
.then((response) => {
if (response.data == true) {
sw = true;
}
})
.catch(error => console.log(error));
if (sw) {
return true;
} else {
return false;
}
}
// console.log('questions', value, testProp, options.some((option) => option[testProp]));
// return true;
}
});
}
when user fill all fields it will check 3 api and that need momnets to check.
and i need to await to get the answer but there is somthing wrong which is not working.
please help
I believe what you want to do is:
async validateBeforeSubmit(event) {
try {
const result = await this.$validator.validateAll();
if (result) {
// go submit
} else {
event.preventDefault();
var elmnt = document.getElementById('drop_zone');
elmnt.scrollIntoView();
}
}
catch (e) {
console.log(e);
}
},
This function is performed on the onChange action. I want only what is under the comment to debounce on 1s. How can I accomplish this?
onChange = (event, { newValue }) => {
this.setState({
value: newValue,
}, () => {
if (this.state.value.length !== 26) {
// this debounce \/
this.Auth.getUsersData(newValue).then(res => {
if (res) {
this.setState({
accountBills: res,
});
}
});
};
});
}
Just extract that code into a new method and wrap it in _.debounce:
import {debounce} from 'lodash';
getUserData = debounce(newValue => this.Auth.getUsersData(newValue)
.then(res => {
if (res) { this.setState({ accountBills: res }) }
})
, 1000);
onChange = (event, { newValue }) => {
this.setState({
value: newValue,
}, () => {
if (this.state.value.length !== 26) {
this.getUserData(newValue);
}
});
}
In my store.js, I have a user_data state, its initial method is fetch_user_data:
export default new Vuex.Store({
state: {
user_data: util.fetch_user_data('username')
...
}
in the util.js:
util.fetch_user_data = function(username){
Lml_http('get', Api_urls.productconfig_common.user_data(username), null, response => {
return response.data // there get the data, in the debugger shows it.
}, error => {
})
}
But when I use the state's user_data, it is undefined.
EDIT-1
I want in the store.js to use the fetch_util's method for fetching data, and commit to the state.
EDIT-2
my lml_http code are bellow:
var lml_http = function (method, url, params, success_cb, error_cb, multipart_formdata=undefined) {
var format_to_form_data = function(data){
let formData = new FormData()
for (let item in data) {
formData.append(item, data[item])
}
return formData
}
var lowercase_method = method.toLowerCase()
var formated_params = params
var header_config = null
if (multipart_formdata) {
header_config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
formated_params = format_to_form_data(formated_params)
}
if(lowercase_method === "get") {
formated_params = {params: formated_params}
if (!header_config) {
Axios.get(url, formated_params).then(response => {
success_cb(response)
return
}).catch(response => {
error_cb(response)
return
})
} else {
Axios.get(url, format_to_form_data(formated_params), header_config).then(response => {
success_cb(response)
return
}).catch(response => {
error_cb(response)
return
})
}
return
}
else {
if(!header_config) {
Axios[method](url, formated_params).then(response => {
success_cb(response)
}).catch(response => {
error_cb(response)
})
return
}else {
Axios[method](url, formated_params, header_config).then(response => {
success_cb(response)
}).catch( response => {
error_cb(response)
})
return
}
}
}
Just create an action to fetch the user data as follows:
export default new Vuex.Store({
state: {
user_data: null
},
mutations: {
setUserData(state, data) {
state.user_data = data;
}
},
actions: {
fetchUserData({ commit }, username) {
Lml_http(
"get",
Api_urls.productconfig_common.user_data(username),
null,
response => {
commit("setUserData", response.data);
},
error => {}
);
}
}
});
Then dispatch this action in the created() hook of theroot vue instance
//main.js
new Vue({
el: "#app",
store,
render: h => h(App),
created() {
this.$store.dispatch("fetchUserData", "username");
}
});
`
Edit:
Axios returns a Promise by default. So in lml_http return Axios calls as below:
var lml_http = function(
method,
url,
params,
success_cb,
error_cb,
multipart_formdata = undefined
) {
var format_to_form_data = function(data) {
let formData = new FormData();
for (let item in data) {
formData.append(item, data[item]);
}
return formData;
};
var lowercase_method = method.toLowerCase();
var formated_params = params;
var header_config = null;
if (multipart_formdata) {
header_config = {
headers: {
"Content-Type": "multipart/form-data"
}
};
formated_params = format_to_form_data(formated_params);
}
if (lowercase_method === "get") {
formated_params = { params: formated_params };
if (!header_config) {
return Axios.get(url, formated_params)
.then(response => {
success_cb(response);
})
.catch(response => {
error_cb(response);
});
} else {
return Axios.get(url, format_to_form_data(formated_params), header_config)
.then(response => {
success_cb(response);
})
.catch(response => {
error_cb(response);
});
}
} else {
if (!header_config) {
return Axios[method](url, formated_params)
.then(response => {
success_cb(response);
})
.catch(response => {
error_cb(response);
});
} else {
return Axios[method](url, formated_params, header_config)
.then(response => {
success_cb(response);
})
.catch(response => {
error_cb(response);
});
}
}
};
Also add a return statement in utils.js
util.fetch_user_data = function(username){
return Lml_http('get', Api_urls.productconfig_common.user_data(username), null, response => {
return response.data // there get the data, in the debugger shows it.
}, error => {
})
}
Now in your action fetchUserData
fetchUserData({ commit }) {
util.fetch_user_data('username').then((
commit("setUserData", response.data);
});
}
In main.js dispatch the action without any payload
//main.js
new Vue({
el: "#app",
store,
render: h => h(App),
created() {
this.$store.dispatch("fetchUserData", "username");
}
});
Because the fetch api is async, it will return a promise, not the response data. I think you may try something like:
const store = new Vuex.Store({
state: {
user_data: null,
...
};
util.fetch_user_data('username')
.then(user => store.user_data = user);
export default store;