Nuxt How to access router from outside a Vue component context - vue.js

In Nuxt.js, I have an exported helper function, which should also programatically navigate the router.
In Vue.js I would normally `import router from "#/router".
How would I migrate this to Nuxt?
doSomething.ts
export default function doSomething(name: string){
console.log(`hello ${name}`);
this.$router.push({ path: "/" }); // this.$router not defined!
}
Component.vue
import doSomething from "#/scripts/doSomething";
export default {
mounted(){
doSomething("name");
}
}

As a workaround I've added this as a first arg:
import Vue from "vue";
export default function doSomething(this: Vue, name: string){
console.log(`hello ${name}`);
this.$router.push({ path: "/" }); // this.$router not defined!
}
and then call it like this:
doSomething.call(this, name);

Type
import VueRouter from 'vue-router'
import {Route} from 'vue-router'
declare module 'vue/types/vue' {
interface Vue {
$router: VueRouter,
$route: Route
}
}
then
window.$nuxt.$router

Related

Uncaught SyntaxError: The requested module '/node_modules/.vite/vue.js?v=535663ae' does not provide an export named 'default'

I'm using a js framework known as griptape(used for blockchain). I'm getting this error when trying to use the vue router.
import Vue from "vue"; //Error **does not provide an export named 'default'**
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue"),
},
];
const router = new VueRouter({
routes,
});
export default router;
while my vue.d.ts file looks like this
import { CompilerOptions } from '#vue/compiler-dom';
import { RenderFunction } from '#vue/runtime-dom';
export declare function compile(template: string | HTMLElement, options?: CompilerOptions): RenderFunction;
export * from "#vue/runtime-dom";
export { }
router.d.ts file look like this
I think you are using Vue 3. You should check your vue-router version. If you just run npm i vue-router now, the version should be "^3.5.3". Try to use npm i vue-router#next to install newer version.
Then export router like this:
import {createRouter, createWebHistory} from 'vue-router'
const routes = [
{
path:'/',
name:"Home",
component:()=>import('./pages/Home.vue')
}
,
{
path:'/about',
name:"About",
component:()=>import('./pages/About.vue')
}
]
const router = createRouter({
history:createWebHistory(),
routes
})
export default router
You technically didn't ask a question I will try to explain the error. Your error states what you try to do, importing a default export from the module 'vue' which doesn't exist.
// some ts file
import Vue from "vue";
// the module
export default {}
If there should be a named export called 'Vue' you should write it as follows: import { Vue } from 'vue'
references:
https://www.typescriptlang.org/docs/handbook/modules.html#default-exports

Access Vue3 global components

So I'm trying to convert this Vue2 project to Vue3(typescript).
It's registering components globally and accessing them to match against a value in my store, however when trying to implement this in Vue3 the components stay undefined.
import getComponentTypeForContent from "../api/getComponentTypeForContent";
import { mapState } from "vuex";
import { defineComponent } from "vue";
export default defineComponent({
name: "PageComponentSelector",
beforeCreate: function () {
console.log("CREATED PAGECOMPONENTSELECTOR");
},
computed: mapState({
model: (state) => state.epiDataModel.model,
modelLoaded: (state) => state.epiDataModel.modelLoaded,
}),
methods: {
getComponentTypeForPage(model) {
// this.$options.components will contain all globally registered components from main.js
return getComponentTypeForContent(model, this.$options.components);
// this.$options.components fetches all components for vue2 app
},
},
});
and registering components like this:
//Pages
import LoginPage from "./components/pages/Login.vue";
const appAdv = createApp(App);
//Register components
appAdv.component("LoginPage", LoginPage);
appAdv.use(store).use(router).mount("#appAdv");
Can't find (or searching badly) how to do this or similar in vue3 so I've come here hoping someone could help hehe
I also frequently use parent components in child components, but don't (or haven't) used the App.component method
In vue3 I usually use the provide/inject . method
Provide
const app = createApp(App);
app.provide('someVarName', someVar); // `Provide` a variable to all components here
Inject:
// In *any* component
const { inject } = Vue;
...
setup() {
const someVar = inject('someVarName'); // injecting variable in setup
return {someVar}
}

vue-router not pushing while inside a store

This is my store
import Vue from 'vue'
import Vuex from 'vuex'
import router from '#/main';
import mainStore from './modules/main-store';
import loginStore from './modules/login-store';
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
mainStore,
loginStore
}
});
and my login-store.js
//other imports
import router from '#/main';
const actions = {
forceLogout(){
localStorage.removeItem('token')
localStorage.removeItem('user')
delete API.defaults.headers.common['Authorization']
router.push('/login')
},
//other actions
}
And my router.js:
import store from './stores'
Vue.use(Router)
const router = new Router({
mode: 'hash',
routes: [
{
path: '/login',
name: 'login',
component: Login,
},
]
//other routes
})
//... some router.afterEach and router.beforeEach
export default router
There is a case where I need the store to force a logout and this is how I do it, I call the forceLogout action from a file named api.js
import store from './../stores';
//....
if(error_msg == 'Not_Logged'){
store.dispatch('forceLogout')
}
//....
I've tried changing an import:
import router from 'vue-router'
//...
router.push('/login')
Same thing with importing
import router from '#/main'
router.push('/login')
and I keep on getting TypeError: Cannot read property 'push' of undefined
I don't see where you're exporting your router.
router.js should include export default router so then when you import router from '#/main' it actually imports something.

How to use vue-i18n inside my vue-route?

My main app.js
import Vue from 'vue'
import language from './language'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale: 'en',
messages: language.messages,
})
import router from './router'
new Vue({
el: '#app',
i18n,
router,
template: '<App/>',
components: { App }
})
The language.js
export default {
messages : {
en: {
hello: 'hello!'
},
ja: {
hello: 'こんにちは!'
},
zh: {
hello: '你好!'
}
}
}
my issue is following route.js code, which I can't use this.$i18n.t('hello'), because $i18n is not available.
import Vue from 'vue'
import Router from 'vue-router'
export const myRouteMap = [
{
path: '/',
component: MyComponent,
redirect: '/myHome',
//name: 'Home',
name: this.$i18n.t('hello') // can't use $i18n here.
}
]
Is there anyone has a similar situation, want to use i18n at vue-route and resolved the issue?
In your example this.i18n is not going to be defined because it is not a Vue instance in the context of that file.
Your root issue is that you are attempting to put display data in the route's definition. This is bad practice in general and results in issues like the one you've run into.
The name property of the route should be a unique identifier of the route and should not change after being defined.
If you want to base a Vue instance's property off of the translated name of the route (which is still too tight a coupling for my taste) you could do that in the Vue component you specified for the route.
computed: {
title() {
return this.$i18n.t(this.$route.name);
}
}
Really, though, you should not base your display data on the route object. Seems like it would be clearer and less work to just specify the translation message key you want to pass to this.$i18n.t in the definition for that related property:
computed: {
title() {
return this.$i18n.t('hello');
}
}

Access router instance from my service

I create a auth service (src/services/auth.js), with just functions and properties ..
export default {
login() { ... }
...
}
Inside login function, I need to redirect user
router.go(redirect)
How can I retrieve router instance?
Context
In my src/main.js file, i create a router ..
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import route from './routes'
const router = new VueRouter({
history: false,
linkActiveClass: 'active'
})
route(router)
const App = Vue.extend(require('./App.vue'))
In my src/routers.js is just map routes
export default function configRouter (router) {
router.map({ .. })
}
You should export the router instance and then import it into the auth.js service.
Here is my workaround with some improvements:
src/routes.js
export default {
'/': {
component: {...}
},
'/about': {
component: {...}
},
...
}
src/router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Routes from './routes'
Vue.use(VueRouter)
const router = new VueRouter({...})
router.map(Routes)
// export the router instance
export default router
src/main.js
import Router from './router'
import App from './app'
Router.start(App, '#app')
src/services/auth.js
import Router from '../router'
export default {
login () {
// redirect
Router.go('path')
}
}
Is your auth service a Vue component?
If so, you should be able to change routes with:
this.$router.go('/new/route');