How i can get router params in apollo ? [VUE3] - vue.js

here is my component script on VueJS. I want to know how to get router params in my apollo component to search item whith these params. The idea is to replace 953 by the id of the page. If you have any questions, ask me ! I'm using createRouter, createWebHashHistory from vue-router and VueJS 4.
Thanks for help.
<script>
import gql from "graphql-tag";
// import { useRouter } from "vue-router";
import TemplatePresentationPage from "./TemplatePresentationPage.vue";
export default {
name: "PresentationPage",
apollo: {
entry: gql`
query entry {
entry(id: 953) {
id
title
}
}
`,
},
components: { TemplatePresentationPage },
setup() {
return {};
},
};
</script>

If your routes looked like this
const routes = [{ path: '/user/:id', component: User }]
then to get that id param on your component you just do as below
const User = {
// make sure to add a prop named exactly like the route param
props: ['id'],
template: '<div>User {{ $route.params.id }}</div>'
}
and this works on your template as well
<template>
<div>User {{ $route.params.id }}</div>
</template>
But as for your case, it seems like you want to use it on your setup() function.
The way you access it is as below
import { useRoute } from 'vue-router';
export default {
setup(){
const route = useRoute();
//console.log(route.params.parameterName)
}
}

Related

vue3, route.push is not a function. I can't find the soluction of this error in google

I create apps with vue3 and laravel.
When I submit text in textbox, addCategory function fires.
at this time, I want to redirect the default page.
But route.push causes below error.
Uncaught (in promise) TypeError: route.push is not a function
This is my code.
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
const addCategory = async () => {
await submitNewCategory()
await getCategories()
newCategory.value = ''
// route.push({name: 'category.show', params: {categoryId: categoryId + 1 }})
route.push('/')
}
</script>
<template>
<div class="form-box">
<h4 style="margin-bottom: 20px; margin-top: 10px">RECIPE HOUSE</h4>
<form method="post" v-on:submit.prevent="addCategory">
<input type="text" v-model="newCategory">
</form>
</div>
</template>
import './bootstrap';
import { createApp } from 'vue/dist/vue.esm-bundler'
import * as VueRouter from 'vue-router'
import CategoryHome from './components/CategoryHome.vue'
import CategoryShow from './components/CategoryShow.vue'
const routes = [
{
path: '/',
name: 'category.home',
components: {
Home: CategoryHome
}
},
{
path: '/categories/:categoryId',
name: 'category.show',
components: {
Show: CategoryShow
},
props: true
},
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes,
})
const app = createApp({})
app.use(router)
app.mount('#app')
Is there some kind of a problem other than router.push?
Thank you for your help.
I'm sorry that My English isn't very good.
Note that router=useRouter() and route=useRoute() are 2 different objects.
The router is the router instance you make with createRouter that handles all the routing. route is the current route instance.
What you want to do is push a route to the router, not the route object (which btw doesn't have a method called push which in turn gives your error),
import { useRouter } from 'vue-router'
const router = useRouter()
const addCategory = async () => {
if (categories.value.length === 0)
{
noData.value = !noData.value
}
await submitNewCategory()
await getCategories()
newCategory.value = ''
// router.push({name: 'category.show', params: {categoryId: categoryId + 1 }})
router.push('/')
}

Nuxt.js unknown store

I'm new to VueJS and try to use the store with NuxtJS.
So, i want to get this (https://nuxtjs.org/guide/vuex-store/) to work.
My store ./store/index.js
import { mapActions, mapGetters } from 'vuex'
export const state = () => ({
temperature: '1234'
})
export const mutations = {setName
setTemperature(state, payload) {
state.temperature = payload
}
}
export const actions = {
getWeatherData({ commit }) {
console.log("set weather to 123")
commit('setTemperature', '123')
}
}
export const getters = {
storeTemperature(state) {
return state.temperature
}
}
export const mixin = {
computed: {
...mapGetters([{
myTemperature: 'weather/storeTemperature'
}])
},
methods: {
...mapActions({
loadWeatherData: 'weather/getWeatherData'
})
}
}
export default mixin
Now i have a simple component to display the temperature:
<template>
<div class="label">
{{ testB }}
</div>
</template>
<style lang="scss" src="./Label.scss"></style>
<script>
import { mixin as WeatherMixin } from '../../store'
export default {
name: 'Label',
//mixins: [WeatherMixin],
props: {
content: {
Type: String,
default: ''
}
},
computed: {
testB () {
return this.$store.state.store.temperature
}
}
}
</script>
I tried to use mapGetters and use it like:
testB () {
return this.myTemperature
}
but this didn't work.
So i tried to use mapState via:
// store
computed: {
...mapState({ temperature: 'temperature' })
}
and use it in the component like
<div class="label">
{{ temperature }}
</div>
But i always didn't get the default value of 1234.
The Vue Console didn't find the store:
But forward to the NuxtJS documentation:
Nuxt.js will look for the store directory, if it exists, it will:
Import Vuex,
Add the store option to the root Vue instance.
What i need to get the store working as expected and how i can access the store state properties? Did i miss something?
To properly manage Vuex in NuxtJS, use namespaced Vuex modules, to keep your state logic properly organized.
For a globally accessible state, you can add these to the ./store/index.js file, while for namespaced modules create a folder with a name of your namespaced module (Preferably no spaces.), then in this folder create files with names actions.js for actions, state.js for states, getters.js for getters and mutations.js for your mutations and export default from each.
You can then access the namespaced state with this.$store.state.<NAMESPACED MODULE NAME>.<STATE VARIABLE>

How to pass data Between vue single file component

I have (my first) app in vue that get data from api and render some select elements.
I want to separe each box to another file (one file for get data from api, second for render select, third for render list).
How can i pass data from
I tried to get data from instance of api:
export default {
props: {
filters: apiIntance.$data.kpis.filters,
For this moment i have something like that:
<!-- src/components/Filters.vue -->
<template>
<div class="filters">
<label v-bind:key="filter.id" v-for="filter in filters">
<select class="js-selectbox">
<option v-bind:value="item.id" v-bind:key="item.id" v-for="item in filter.items">{{item.name}}</option>
</select>
</label>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import Api from './ApiTest.vue';
export default {
props: {
filters: //Get Data from ApiTest.vue
},
};
</script>
<!-- src/components/ApiTest.vue -->
export default Vue.extend({
data(): DataObject {
return {
kpis: {
...
},
};
},
Have you some tips how to get data in one file and spread it for other files?
You might be looking for Vuex which is a vue data management plugin that all your components will have access to
import Vue from 'vue'
import Vuex from 'vue'
Vue.use(Vuex)
const store = new Vuex.Store({
// data will be stored here
state: {
apiData: null,
},
mutations: {
// you call this mutation to add data
apiData(state) {
state.apiData = apiData
}
},
getters: {
// a getter for the data
apiData(state) {
retrun state.apiData
}
}
})
// new Vue({...,store})
you can add data to the store immediately after the fetching with :
this.$store.commit('apiData',yourdatahere)
and then access/get it on any component with :
this.$store.getters.apiData
you can read more about Vuex
There are numerous ways, to name a few
one file for get data from api don't need to be a vue instance. You may want to add more hooks.
// ApiService.ts
export const ApiService = { getData: () => {/**/} }
// src/components/Filters.vue
...
<script lang="ts">
import Vue from 'vue';
import {ApiService} from '#/.../ApiService'
export default {
data: () => ({
filters: []
}),
created() {
ApiService.getData().then(data => this.filters = data)
}
};
</script>
You can certainly make a Vue instance to provide data, to make it reactive and component independent from data logic. For example:
// ApiService.ts
const ApiService = new Vue({
data: () => ({
filters: []
}),
created() {
request().then(data => this.filters = data)
}
})
// src/components/Filters.vue
...
<script lang="ts">
import Vue from 'vue';
import {ApiService} from '#/.../ApiService'
export default {
computed: {
filters() {
return ApiService.filters
}
}
};
</script>

How to get current name of route in Vue?

I want to get the name of the current route of vue-router, i have a component menu with navigation to another componentes, so i want to dispaly the name of the current route.
I have this:
created(){
this.currentRoute;
//this.nombreRuta = this.$route.name;
},
computed:{
currentRoute:{
get(){
this.nombreRuta = this.$route.name;
}
}
}
But the label of the name of the route does not change, the label only show the name of the first loaded route.
Thank You
EDIT:
Image to show what i want
You are using computed incorrectly. You should return the property in the function. See the docs for more information.
Here is your adapted example:
computed: {
currentRouteName() {
return this.$route.name;
}
}
You can then use it like this:
<div>{{ currentRouteName }}</div>
You can also use it directly in the template without using a computed property, like this:
<div>{{ $route.name }}</div>
Vue 3 + Vue Router 4
Update 5/03/2021
If you are using Vue 3 and Vue Router 4, here is two simplest ways to get current name of route in setup hook:
Solution 1: Use useRoute
import { useRoute } from 'vue-router';
export default {
setup () {
const route = useRoute()
const currentRouteName = computed(() => route.name)
return { currentRouteName }
}
}
Solution 2: Use useRouter
import { useRouter } from 'vue-router';
export default {
setup () {
const router = useRouter()
const currentRouteName = computed(() => router.currentRoute.value.name;)
return { currentRouteName }
}
}
I use this...
this.$router.history.current.path
In Composition API, this works
import { useRouter } from 'vue-router'
const router = useRouter()
let currentPathObject = router.currentRoute.value;
console.log("Route Object", currentPathObject)
// Pick the values you need from the object
I used something like this:
import { useRoute } from 'vue-router';
then declared
const route = useRoute();
Finally if you log route object - you will get all properties I used path for my goal.
This is how you can access AND watch current route's name using #vue/composition-api package with Vue 2 in TypeScript.
<script lang="ts">
import { defineComponent, watch } from '#vue/composition-api';
export default defineComponent({
name: 'MyCoolComponent',
setup(_, { root }) {
console.debug('current route name', root.$route.name);
watch(() => root.$route.name, () => {
console.debug(`MyCoolComponent- watch root.$route.name changed to ${root.$route.name}`);
});
},
});
</script>
I will update this answer once Vue 3.0 and Router 4.0 gets released!
I use this...
this.$route.name
In my Laravel app I created a router.js file and I can access the router object in any vue component like this.$route
I usually get the route like this.$route.path
Using composition API,
<template>
<h1>{{Route.name}}</h1>
</template>
<script setup>
import {useRoute} from 'vue-router';
const Route = useRoute();
</script>
Using Vue 3 and Vue Router 4 with Composition API and computed:
<script setup>
import { computed } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
// computed
const currentRoute = computed(() => {
return router.currentRoute.value.name
})
</script>
<template>
<div>{{ currentRoute }}</div>
</template>
⚠ If you don't set a name in your router like so, no name will be displayed:
const routes = [
{ path: '/step1', name: 'Step1', component: Step1 },
{ path: '/step2', name: 'Step2', component: Step2 },
];
In Vue 3.2 using Composition API
<script lang="ts" setup>
import { useRoute } from "vue-router";
const route = useRoute();
const currentRouteName = computed(() => {
return route.name;
});
</script>
<template>
<div>
Using computed:{{currentRouteName}}
or without using computed: {{route.name}}
</div>
</template>
This is how you can get id (name) of current page in composition api (vue3):
import { useRoute } from 'vue-router';
export function useFetchPost() {
const currentId = useRoute().params.id;
const postTitle = ref('');
const fetchPost = async () => {
try {
const response = await axios.get(
`https://jsonplaceholder.typicode.com/posts/${currentId}`
);
postTitle.value = response.data.title;
} catch (error) {
console.log(error);
} finally {
}
};
onMounted(fetchPost);
return {
postTitle,
};
}
I'm using this method on vue 3 & vue-router 4
It works great!
<script>
import { useRoute } from 'vue-router'
export default {
name: 'Home',
setup() {
const route = useRoute();
const routeName = route.path.slice(1); //route.path will return /name
return {
routeName
}
}
};
</script>
<p>This is <span>{{ routeName }}</span></p>
I've Tried and it Worked:
Use Following in Your Elements;
{{ this.$route.path.slice(1) }}
this.$router.currentRoute.value.name;
Works just like this.$route.name.
Vue 3 + Vue Router 4 + Pinia store (or any other place outside of vue components)
#KitKit up there gave an example how to get route if you are using Vue 3 and Vue Router 4 in setup hook. However, what about state management in Pinia store ?
In vue#2 and vue-router#3.5.1: We could have used router.currentRoute.query.returnUrl like so (example in vuex state management):
import router from "#/router";
const state = initialState;
const getters = {};
const actions = { // your actions };
const mutations = {
loginSuccess(state, user) {
let returnUrl = "";
if(router.currentRoute.query.returnUrl != undefined)
returnUrl = router.currentRoute.query.returnUrl;
},
};
export default {
state,
getters,
actions,
mutations,
};
export const authentication = {
actions: {},
mutations: {},
};
In vue#3 and vue-router#4: We have to append value to currentRoute like so:
import router from '#/router';
export const authenticationStore = defineStore('authUser', {
state: (): State => ({
// your state
}),
getters: {
// your getters
},
actions: {
loginSuccess(user: object) {
let returnUrl = '';
if (router.currentRoute.value.query.returnUrl != undefined)
returnUrl = router.currentRoute.value.query.returnUrl;
},
},
});

get all routes in a vue router

Am trying to create a simple menu using vue router , id like to iterate all routes and display in my menu , currently am using below instance method in my component but i just get a function , how would i iterate to get individual routes ?
methods : {
getMenuLinks: function() {
var t = this.$router.map() ;
//t returns a vue object instance
return t._children ;
// did not know how to iterate this
}
}
I want to iterate all maped routes to get something like below of each mapped route :
<a v-link="{ path: 'home' }">Home</a>
In Nuxt, the routes are generated automatically so I couldn't do what #zxzak suggested.
Here's what you can do in that case.
<template v-for="item in items">
<b-nav-item :to="item.path">
{{item.name}}
</b-nav-item>
</template>
export default {
created() {
this.$router.options.routes.forEach(route => {
this.items.push({
name: route.name
, path: route.path
})
})
}
, data() {
return {
items: []
}
}
}
You can simply iterate over $router.options.routes in your template:
<nav>
<router-link v-for="route in $router.options.routes" :key="route.path" :to="route.path">{{ route.name }}</router-link>
</nav>
Maybe add styling for the selected route:
:class="{ active: route.path === $router.currentRoute.path }"
edit: for active class, use https://router.vuejs.org/api/#active-class instead
Since vue-router 3.5, Router instance has now a getRoutes() method.
So an up to date answer could be
<router-link
for="r in routes"
:key="r.path"
:to="r.path"
>
{{ r.name }}
</router-link>
computed: {
routes() { return this.$router.getRoutes() }
}
Instead of relaying on Vue's internals, put routes inside the data of your starting component.
var map = {
'/foo': {
component: Foo
},
'/bar': {
component: Bar
}
}
var routes = Object.keys(map)
var App = Vue.extend({
data: function() {
return {
routes: routes
}
}
})
router.map(map)
router.start(App, '#app')
http://jsfiddle.net/xyu276sa/380/
Another solution is using Webpack's require.context
// search for src/pages/**/index.vue
function routesGen () {
const pages = require.context('./pages/', true, /index\.vue$/)
const filePaths = pages.keys()
const getRoutePath = filePath => filePath.match(/\.(\/\S+)\/index\.vue/)[1]
return filePaths.map(filePath => ({
path: getRoutePath(filePath),
component: pages(filePath).default
}))
}
As VueRouter is simply a JavaScript class as other classes, you can extend it and add any custom functionality including the questionable one:
// TypeScript
import Vue from 'vue';
import VueRouter, { RouteConfig } from 'vue-router';
class VueRouterEx extends VueRouter {
matcher: any;
public routes: RouteConfig[] = [];
constructor(options) {
super(options);
const { addRoutes } = this.matcher;
const { routes } = options;
this.routes = routes;
this.matcher.addRoutes = (newRoutes) => {
this.routes.push(...newRoutes);
addRoutes(newRoutes);
};
}
}
Vue.use(VueRouterEx);
const router = new VueRouterEx({
mode: 'history',
base: process.env.BASE_URL,
routes: [],
});
export default router;
So, from any component, you can get the routes using this.$router.routes