How to access query string in nuxtjs and pass it to data - vue.js

I want to access query strings from url in nuxtjs page.
this is the page url with query strings -
http://localhost:3000/en-IN/atrsps/results/?pickupairport=Dubai&dropoffpoint=Bur%20Dubai,%20DU,%20United%20Arab%20Emirates&pickupdate=06%2F06%2F2021%2013%3A27
this is the my page script part
<script>
import axios from 'axios'
export default {
data() {
return {
cars: [],
loading: false,
disabled: true,
pickupairport: null,
dropoffpoint: null
}
},
asyncData({ route }) {
console.log(route.query)
},
computed: {
url() {
return `https://api.testdomain.com/V2/transfers/carlist?startpoint=${this.pickupairport}&endpoint=${this.dropoffpoint}&pickupdate=2021-07-01&pickuptime=14:55`
},
},
async created() {
await this.fetchData()
},
methods: {
async fetchData() {
this.loading = true //the loading begin
const res = await axios.get(this.url)
this.cars = res.data.response
this.loading = false
},
carsearch($state) {
setTimeout(() => {
axios
.get(this.url)
.then((res) => {
if (res.data.response.length > 1) {
res.data.response.forEach((item) => this.cars.push(item))
$state.loaded()
} else {
$state.complete()
}
})
.catch((err) => {
console.log(err)
})
}, 1000)
},
},
}
</script>
I want to pass pickupairport and dropoffpoint value from url to pickupairport & dropoffpoint in data.
in console, i can see this data
{
pickupairport: 'Dubai',
dropoffpoint: 'Bur Dubai, DU, United Arab Emirates',
pickupdate: '06/06/2021 13:27'
}

from the template you can access to it from $route object like $route.query and from the vue instance you can write this.$route.query
also you can check the $route object from vue dev tools. check out the picture below:
to pass the queries to data object you can just write:
data() {
return {
pickupairport: this.$route.query.pickupairport,
}
}
but you might not need to store the query in data object since you have access to $route object either from template or anywhere in your script

Related

Nuxt js Router Push Not Working After Delete

I've created a simple CRUD with Nuxt. Data is provided by Lumen. I got a problem with the DELETE, data is deleted but Nuxt does not redirect to the other page.
Here is my script:
<script>
export default {
name: 'EmployeePage',
data() {
return {
fields: ['name','email','image','address'],
emplyees:[],
}
},
mounted() {
this.$axios.get('/employee').then(response => {
this.pegawais = response.data.data
}).catch(error => {
console.log(error.response.data)
})
},
methods: {
async delete(id) {
await this.$axios.delete(`/employee/${id}`).then(response => {
this.$router.push({ name: 'employee' }) <-----this redirect not working
})
}
}
}
</script>
I want Nuxt to redirect to the employee page that display all the data after the deletion.
You should not mix async/await and .then. Use the first approach, that way you will not have the .then callback hell and it will be cleaner overall.
Like this
<script>
export default {
name: 'EmployeePage',
data() {
return {
fields: ['name', 'email', 'image', 'address'],
emplyees: [],
}
},
async mounted() {
try {
const response = await this.$axios.get('/employee')
this.pegawais = response.data.data
} catch (error) {
console.log(error.response.data)
}
},
methods: {
async delete(id) {
await this.$axios.delete(`/employee/${id}`)
await this.$router.push({ name: 'employee' })
},
},
}
</script>
await this.$router.push does not require an await but it's a Promise too, so I'm writing it like that in case you need to call something else afterwards.
this.$axios.$get('/employee') can also be used if you want to remove a .data aka this.pegawais = response.data as shown here.

How to get value of Vuex getter inside of Vue local data object

Hey this seemed to be pretty simple, but I just can't figure out how to get my loggedInUser object to work outside the template. I read through a bunch of other answers and I know I have to do something to store the getter in a local data object.
I have a temporary 'id' object set up because that's what I ultimately want to set to loggedInUser.id in order to attach to my Axios request.
Here's the page I want to make changes on:
<script>
import { mapGetters } from 'vuex'
// import vuex from 'vuex'
export default {
data: () => ({
results: "",
id: "15",
}),
computed: {
...mapGetters(['loggedInUser'])
},
// var id = {{loggedInUser}};
methods: {
getData() {
this.$axios.get('http://127.0.0.1:8000/api/v1/actors/',
{params: {user: this.id} }
)
.then(response => {this.results = response.data});
}
}
}
</script>
and here's my index.js for store:
export const getters = {
isAuthenticated(state) {
return state.auth.loggedIn
},
loggedInUser(state) {
return state.auth.user
}
}
The mapGetters helper simply maps store getters to local computed
properties
This:
computed: {
...mapGetters(['loggedInUser'])
},
Is equivalent to this:
computed: {
loggedInUser() {
return this.$store.getters.loggedInUser
},
},
Replace this.id with this.loggedInUser.id in your axios request, and get rid of the temporary id data property.
getData() {
this.$axios.get('http://127.0.0.1:8000/api/v1/actors/', {
params: {
user: this.loggedInUser.id
}
})
.then(response => {
this.results = response.data
});
}
We are assuming getData only gets called when the user is authenticated. If that's not the case, have in mind this.loggedInUser may be null or undefined and accessing this.loggedInUser.id will throw an error.

Vue + Axios with sessionStorage

Goal: Initially load posts using the Wordpress Rest API via Axios once in a Vue View, and only once during a session of visiting the Vue website.
Current Result: I currently fetch the results successfully and set them in sessionStorage. They display correctly. I want to know/learn if I am accomplishing this correctly and have the process optimized in the best way possible. I've looked up documentation and I think I have it down.
Current Code:
<script>
import Hero from "#/components/Hero.vue";
import axios from "axios";
export default {
name: "About",
components: {
Hero,
},
data: function() {
return {
eatery: [],
};
},
created() {
axios
.get("//localhost:81/wp-json/wp/v2/posts?_embed&per_page=5&categories=2")
.then((response) => {
sessionStorage.setItem("eatery", JSON.stringify(response.data));
})
.catch((error) => {
window.alert(error);
});
},
mounted() {
if (sessionStorage.getItem("eatery")) {
this.eatery = JSON.parse(sessionStorage.getItem("eatery"));
}
},
};
</script>
I would check whether it's in the storage before trying to load it. In your case, it would look like this:
export default {
name: "About",
components: {
Hero,
},
data: function() {
return {
eatery: [],
};
},
loadEatery() {
axios
.get("//localhost:81/wp-json/wp/v2/posts?_embed&per_page=5&categories=2")
.then((response) => {
sessionStorage.setItem("eatery", JSON.stringify(response.data));
return response.data;
})
.catch((error) => {
console.error(error); // for debugging maybe
});
},
mounted() {
if (sessionStorage.getItem("eatery")) {
this.eatery = JSON.parse(sessionStorage.getItem("eatery"));
} else {
loadEatery().then(data => this.eatery = data);
}
},
};

How to check if JSON data is loaded

I use axios to fetch my JSON file en vuex for using the fetched data over multiple components.
The thing is that my page renders before all data is loaded.
The following works because I delayed the rendering by 2 seconds, without this timeout it would result in an error.
I would like to do this the proper way but am not sure how to do it.
STORE.JS
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
poss: null
},
getters: {
NAME: state => {
return state.name
},
POSS: state => {
return state.poss
}
},
mutations: {
SET_POSS : (state,payload) => {
state.poss = payload
},
ADD_POSS : (state,payload) => {
state.poss.push(payload)
},
},
actions:{
GET_POSS : async (context,payload) => {
let { data } = await axios.get("json/poss.json")
context.commit('SET_POSS',data)
},
SAVE_POSS : async (context,payload) => {
let { data } = await axios.post("json/poss.json")
context.commit('ADD_POSS',payload)
}
}
});
COMPONENT.VUE
module.exports = {
mounted:function(){
var self = this;
setTimeout(function () {
self.mkPageload()
}, 2000);
},
methods: {
mkPageload: function(){
let positions = this.$store.getters.POSS.pos
Object.keys(positions).forEach(key => {
// rendering
}
}
}
}
The desired result is that the page is only rendered after all data from the JSON file has been loaded.
There are several ways to solve this.
You could use wait / async in your component.
async mounted () {
await userStore.getAll()
// access getter and render
},
Your could watch vuex variable like (could be done without async but I like to add them)
async mounted () {
await userStore.getAll()
},
computed: {
...mapGetters('users')
},
watch: {
users(newValue, oldValue) {
....
// render
}
}
dont'forget to import the mapGetters: https://vuex.vuejs.org/guide/getters.html

Vuex update state by using store actions

I have two functions in my store, one that gets data by calling API and one that toggles change on cell "approved". Everything working fine, except that when I toggle this change it happens in database and I get the response that it is done but It doesn't update on UI.
I am confused, what should I do after toggling change to reflect change on UI, should I call my API from .then or should I call action method responsible for getting data from server.
export default {
state: {
drivers: {
allDrivers:[],
driversError:null
},
isLoading: false,
token: localStorage.getItem('token'),
driverApproved: null,
driverNotApproved: null
},
getters: {
driversAreLoading (state) {
return state.isLoading;
},
driverError (state) {
return state.drivers.driversError;
},
getAllDrivers(state){
return state.drivers.allDrivers
}
},
mutations: {
getAllDrivers (state) {
state.isLoading=true;
state.drivers.driversError=null;
},
allDriversAvailable(state,payload){
state.isLoading=false;
state.drivers.allDrivers=payload;
},
allDriversNotAvailable(state,payload){
state.isLoading=false;
state.drivers.driversError=payload;
},
toggleDriverApproval(state){
state.isLoading = true;
},
driverApprovalCompleted(state){
state.isLoading = false;
state.driverApproved = true;
},
driverApprovalError(state){
state.isLoading = false;
state.driverError = true;
}
},
actions: {
allDrivers (context) {
context.commit("getAllDrivers")
return new Promise((res,rej)=>{
http.get('/api/admin/getAllDrivers').then(
response=>{
if (response.data.success){
let data=response.data.data;
data=data.map(function (driver) {
return {
/* response */
};
});
context.commit("allDriversAvailable",data);
res();
}else {
context.commit("allDriversNotAvailable",response.data)
rej()
}
})
.catch(error=>{
context.commit("allDriversNotAvailable",error.data)
rej()
});
});
},
toggleDriverApproval (context, payload){
return new Promise((res, rej)=>{
http.post("/api/admin/toggleDriverApproval",{
driver_id: payload
})
.then( response => {
context.commit('driverApprovalCompleted');
res();
}).catch( error =>{
context.commit('driverApprovalError');
rej()
})
})
}
}
}
and here is the code on the view, I wrote the necessary code for better clarification of the problem
export default {
name: 'Drivers',
data: () => ({
data: [],
allDrivers: [],
driversErrors: []
}),
created() {
this.$store
.dispatch('allDrivers')
.then(() => {
this.data = this.$store.getters.getAllDrivers
})
.catch(() => {
this.errors = this.$store.getters.driverError
})
},
computed: {
isLoading() {
return this.$store.getters.driversAreLoading
}
},
methods: {
verify: function(row) {
console.log(row)
this.$store.dispatch('toggleDriverApproval', row.id).then(() => {
this.data = this.$store.getters.getAllDrivers
console.log('done dis')
})
},
},
}
if I understand your issue, you want the UI displaying your data to change to the updated data after making a post request.
If you are using Vuex you will want to commit a mutation, and use a getter display the data.
I am not sure how your post request is being handled on the server but if successful typically you would send a response back to your front end with the updated data, and commit a mutation with the updated data.
Example:
Make a Post request
toggleDriverApproval (context, payload){
return new Promise((res, rej)=>{
http.post("/api/admin/toggleDriverApproval",{
driver_id: payload
})
.then( response => {
context.commit('driverApprovalCompleted', response.data);
res();
}).catch( error =>{
context.commit('driverApprovalError', error.response.data);
rej()
})
})
}
If succesful commit the mutation
.then( response => {
context.commit('driverApprovalCompleted', response.data);
res();
})
response.data being your data you want to mutate the state with.
Mutation Example:
customMutation(state, data) {
state.driverApproval = data
}
Getter Example:
driver(state) {
return state.driverApproval
}
displaying the getter in a template
<template>
<div v-if="driver">{{driver}}</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: Example,
computed: {
driver() {
return this.$store.getters.driver
},
// or use mapGetters
...mapGetters(['driver'])
}
}
</script>
more examples can be found at Vuex Docs