how to withot reload page call api.services.js externl file - vue.js

api.service.js
const shop = localStorage.getItem('shopid');
async getProduct() {
return axios.get(API_URL+'/product/all?installation_id='+shop, { headers: authHeader() })
.then((res) => res.data);
}
AppTopbar.vue
<Dropdown v-model="selected" :options="storesLists" #change="onChange" optionLabel="name" :filter="true" />
onChange(event) {
console.log(event.value);
localStorage.setItem('shopid',event.value);
}
here AppTopbar is common for all vue files(ex.products.vue,bill.vue).
if i change dropdown it set to localStorage then get data like id wise(axios.get(API_URL+'/product/all?installation_id='+shop).
its working fine but i only reload then get record.
how to withot reload page call api.services.js externl file.

Related

Problem with rendering data and heavy data loading

The first problem is that when getDetails(‘multiple’, ‘2’) function is called inside HTML, it takes some time until de data is displayed from v-for.
The second problem is that when I call the console.log(userDetails) from inside of anotherFunction() I got the undefined answer. It doesn’t wait for the this.getDetails(‘multiple’, ‘1’) to execute completely.
How can I improve the time for rendering, or should I use another way to display de data?
How can I make the second function to wait until the first function is complete?
VUE version: 2.7.10
<div id="app">
<p v-for="item in userDetails">item is displayed</p> //
<button #click="anotherFunction()">Click Me!</button>
</div>
<script>
export default {
name: 'App',
data: {
userDetails: []
}
}
// axios function
getDetails(actionType, idUser) {
axios.post("https://example.com/link", {
Username: username
}).then(response => {
const result = response.data;
// push data into variable
this.userDetails.push(result[0])
}).catch(error => {
this.showError('Error', 4000);
console.error('Error:' + error);
});
// another function from where I want to call the axios function
anotherFunction() {
this.getDetails('multiple', '1')
// call the userDetails into another function will output "undefined"
console.log(this.userDetails);
}

Fetching data from json server in vue with axios

I would like to know is there is a way to do something like this without backend. I am calling all data from json server and displaying on home page:
async created() {
try{
const products = await axios.get('http://localhost:3000/products')
this.products = products.data
} catch(err) {
console.log(err)
}
}
Now when i click any of these products i would like to redirect user to new page and would like to display data of that specific object from json server.
What i have built for now is when user click on any product he gets redirected to route /product, and everything is hardcoded there, no dynamic data.
I hope my question is clear, thank you everybody.
You should consider using Vuex for this.
Move your method from created() to vuex's action and then call it in the hook.
The Vuex store's code is gonna be something like this:
state: {
products: []
},
getters: {
getProductById: (state) => (id) => state.products.find(product.id === id)
},
mutations: {
SET_PRODUCTS(state, products) {
state.products = products
}
},
actions: {
// this one is to call from the hook
fetchProducts({ commit }) {
return axios.get('http://localhost:3000/products').then(res => {
commit('SET_PRODUCTS', res.data)
})
}
}
Then call something like this from the component you're redirecting from:
<router-link
:to="{
name: 'Product', // im assuming this is the /product route's name
params: {
id: product.id // product.id is the id of your specific object your clicked on
}"
>
{{ product.productName }}
</router-link>
In your <Product /> component, you get the specific object by id from your Vuex store by using the getProductById() getter.
In your template:
...
<!-- the id we've passed as a route params -->
<h1>{{ getProductById($route.params.id) }}</h1>
...

Fetching data with axios from json server

I know how to get all the data from the json server, but now I would like to know if there is a way to call a certain number of say products, because I want to add a button when the user clicks on it and then make another call and display a few more products on the page...I am using Vue, and this is just an exercise project and i am only creating view, so thats why i am using json server
<template>
<div v-for="product in products" :key="product.name">
<Product :product="product" />
</div>
</template>
<script>
data() {
return {
products: []
}
},
async created() {
try{
const response = await axios.get('http://localhost:3000/products')
this.products = response.data
} catch(err) {
console.log(err)
}
}
</script>
You can use the _limit and _page query parameters in your route.
// Get products 1-10
const response = await axios.get('http://localhost:3000/products?_limit=10&_page=1')
// Get products 11-20
const response = await axios.get('http://localhost:3000/products?_limit=10&_page=2')
// Get products 31-45
const response = await axios.get('http://localhost:3000/products?_limit=15&_page=3')

Vuex: How to grab latest user data after user profile updated?

I am using Vuex and having trouble getting a user's data to be "reactive" after his profile has been updated. Here's my scenario:
My App.vue checks a user's properties during the created() hook
like so:
async created() {
await this.$store.dispatch('getSSOUser') // gets user from auth server
await this.$store.dispatch('fetchUserProfiles') // queries known user table to see if user has a profile
// set for global user state throughout app
await this.setUser()
// then loads the UI
this.isBusy = false
methods: {
setUser() {
const user = this.getUserProfileBySSOID(this.ssoUser.data.user_id)
this.$store.commit('SET_USER', user)
}
So now I have the user's profile (user object) to use throughout the app. Works good....but...when a user edits his profile in the app (for example, updates his phone number, etc) and clicks submit, I can't seem to get the state to refresh/see that there has been a change unless the user manually refreshes the page.
What is the recommended way to handle this issue? Do I need to run a dispatch to the user state on every route change? The user's profile is located at path: '/userEdit/:uid'
This is my app structure:
<div id="app">
<Banner />
<section class="container-fluid">
<loading-spinner v-if="isBusy"></loading-spinner>
<div v-else>
<AuthName class="text-right" />
<MainNav />
<main id="routerView">
<transition name="component-fade" mode="out-in">
<RouterView :key="$route.fullPath" />
</transition>
</main>
</div>
</section>
</div>
User profile update function:
ApiService.putUserProfile(this.user)
.then(() => {
this.loading = false
this.$router.push('/admin/users')
}
})
.catch(err => {
if (err.response) {
this.errors = err.response.data
} else {
if (err.request) {
this.errors = err.request
} else {
this.errors = err.message
}
}
this.loading = false
console.error('Error from update', err)
})
after you update the detail of the user you can fire an event which may will fetch the data from the server behind the scene.
methods:{
loadData(){
await this.$store.dispatch('getSSOUser') ;
await this.$store.dispatch('fetchUserProfiles');
await this.setUser()
this.isBusy = false
},
updateInfo() {
this.form.put('api/profile').then((response) => {
let userData = response.data.userdata;
Fire.$emit('ProfileEvent');
}
},
},
created(){
this.loadData();
Fire.$on('ProfileEvent', () => {
this.loadData();
});
}
may be firing an event after the there is any changes saved in the profile page and executing the function that is called when the component is created after the fired event may resolve your problem. Hope you will get the idea from above code example.

Vuejs testing value after click

<!-- template -->
<div>
<textarea v-model="someText">{{someText}}</textarea>
<div v-if="hasError">Something wrong here</div>
<input v-on:click="store" type="submit" value="update" />
</div>
//script
{
data() {
hasError: false,
someText: ""
},
store(){
return axios.post('/my/api/endpoint', { myvalue: this.someText })
.then(() => {
this.hasError= false;
})
.catch(() => {
this.hasError= true;
};
}
}
//test
import { mount } from 'vue-test-utils';
import MyComponent from "./component.vue";
import * as httpMock from 'moxios';
import Vue from "vue";
it("notifies when updates fail", (done) => {
const wrapper = mount(MyComponent);
httpMock.stubFailure("PUT", "/my/api/endpoint",
{
status: 500
});
httpMock.wait(() => {
wrapper.find(".button").trigger ("click");
Vue.nextTick(() => {
expect(wrapper.html()).toContain("Something wrong here");
done();
});
});
I have the above code to test error state in the vue app. Simply, i'm trying to test that if there is an error calling the server, a bit of text is displayed to say so. i've manually tested this in the browser and its all good, but i can't get a unit test around it. it just fails, saying expected '...' does not contain Something wrong here
probably something to do with the dom not being updated yet? But I thought that was what Vue.nextTick was for?
You're running wait before you actually trigger the axios call. Your call of the click event must be outside of wait.
wrapper.find(".button").trigger ("click");
httpMock.wait(() => {
Vue.nextTick(() => {
expect(wrapper.html()).toContain("Something wrong here");
done();
});
})
Also, I'm assuming you're importing axios in the component, as I don't actually see the import.