Quasar framework : Navigation guards with file boot doesn't? - vue.js

i just make register app to test login , register and navigation guards but always i can open the link i will put the code to help me
router/routes.js
const routes = [
{
path: '/',
component: () => import('layouts/MainLayout.vue'),
children: [
{
path: '',
meta:{signIn:true},
component: () => import('pages/Index.vue')
},
{
path: 'login',
component: () => import('pages/auth.vue')
},
]
}
]
// Always leave this as last one
if (process.env.MODE !== 'ssr') {
routes.push({
path: '*',
component: () => import('pages/Error404.vue')
})
}
export default routes
this is file boot :boot/router-auth.js
// import something here
import {firebaseAuth} from "boot/firebase"
// "async" is optional
export default ({ router/* app, router, Vue, ... */ }) => {
// something to do
router.beforeEach((to,from,next) =>{
if(to.matched.some(route =>route.meta.signIn)){
if(firebaseAuth.currentUser)
{
next()
}else{
//next({ path: "/auth" })
//Router.push("/auth")
console.log("maldkds");
next({path:"/login"})
}
}
next()
//{ path: "/login" }
})
}
and this is my MainLayout.vue
<template>
<q-layout view="lHh Lpr lFf">
<q-header elevated>
<q-toolbar>
<q-toolbar-title class="text-center">
{{title}}
</q-toolbar-title>
<div class="row">
<q-btn flat dense round v-if="!userDetails.userId" color="white" icon="person" no-caps label="Login" />
<q-btn flat dense round v-else color="white" icon="person" no-caps #click="logoutUser" >Logout <br/> {{userDetails.name}} </q-btn>
</div>
<div></div>
</q-toolbar>
</q-header>
<q-page-container>
<router-view />
</q-page-container>
</q-layout>
</template>
<script>
import {mapState,mapActions} from "vuex"
export default {
name: 'MainLayout',
data () {
return {
}
},
computed:{
...mapState("store",["userDetails"]),
title(){
if(this.$route.fullPath=="/"){
return "Register App"
} else if(this.$route.fullPath=="/login"){
return "Auth"
}
}
},
methods:{
...mapActions("store",["logoutUser"]),
}
}
</script>
<style>
.q-toolbar .q-btn{
line-height: 1.2;
}
</style>
Finally i have always this error:
NavigationDuplicated
_name: "NavigationDuplicated" name: "NavigationDuplicated" message: "Navigating to current location ("/login") is not allowed"

I resolved by creating const Router and exporting, after Route, use beforeEach with you validate.
import Vue from 'vue'
import VueRouter from 'vue-router'
import { isAuth, isAdmin, isUser } from "./auth";
import routes from './routes'
Vue.use(VueRouter)
const Router = new VueRouter({
mode: process.env.VUE_ROUTER_MODE,
base: process.env.VUE_ROUTER_BASE,
scrollBehavior: () => ({ y: 0 }),
routes
})
Router.beforeEach((to,from, next) => {
to.matched.some( route =>{
if(route.meta.requiresAuth){
if(!isAuth()){
next({ path: '/' })
}
}
next()
})
})
export default Router

Put debugger as the first line of your router.beforeEach() and examine what is inside to.matched. It is possible that it is matching the route with path '' and it may redirect /login to /login, aka. redirect loop.

Related

Missing required prop: "slug" - Vue 3

Im build project on forntend vue and backend django. I stuck with problem what i can't resolv.
I trying to send data from ProjectsView.vue to ProjectDetailView.vue. Im trying to use props but i get error:
[Vue warn]: Missing required prop: "slug"
ProjectsView.vue don't send data to ProjectDetailView.vue and axios throw a error
GET http://127.0.0.1:8000/api/v1/projectdetail/undefined/ 500 (Internal Server Error)
I can't find problem in this code.
this is my ProjectsView:
<template>
<div class="container d-flex d-xl-flex justify-content-xl-center">
<div class="d-flex d-sm-flex d-md-flex d-lg-flex d-xl-flex justify-content-center flex-wrap justify-content-sm-center justify-content-md-center justify-content-lg-center justify-content-xl-center">
<div v-for="prof in projects" v-bind:key="prof.id">
<div class="card" style="width: 285px;height: 400px;margin: 5px;border-radius: 15px;">
<div class="card-body text-center">
<img class="img-fluid" :src="prof.avatar" style="width: 150px;border-width: 1px;border-radius: 100px;" />
<h4 class="card-title">
<router-link
:to="{ name: 'projectdetail', params: { slug: prof.slug } }"
>{{ prof.title }}
</router-link>
<fa v-if="prof.is_online" icon="circle" data-bs-toggle="tooltip" title="Online" style="color: rgb(0,197,67);font-size: 12px;padding: 0px;margin-top: 0px;" /></h4>
<h6 class="text-muted card-subtitle mb-2">{{ prof.about }}</h6>
<h6 class="text-muted card-subtitle mb-2">{{ prof.last_online_at }}</h6>
<div v-if="prof.tahs">
<div class="d-inline-block" v-for="tag in prof.tahs.split(',')" v-bind:key="tag">
<span class="badge rounded-pill bg-secondary" style="margin: 1px;">{{tag}}</span>
</div>
</div>
<p class="card-text"></p><a class="card-link" href="#">Link</a><a class="card-link" href="#">Link</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import { useToast } from "vue-toastification";
import Project from '#/views/DetailProjectView.vue'
export default {
name: 'Projects',
setup() {
// Get toast interface
const toast = useToast();
return { toast }
},
data() {
return {
projects: [],
errors: [],
}
},
mounted() {
this.getItemsProjects()
},
components: {
Project,
},
methods: {
async getItemsProjects() {
this.$store.commit('setIsLoading', true)
axios
.get('/api/v1/projects/')
.then(response => {
this.projects = response.data
console.log(this.projects)
})
.catch(error => {
console.log(error)
})
this.$store.commit('setIsLoading', false)
},
}
}
</script>
and this is my ProjectDetailView.vue
<template>
<div>working? {{slug}}
</div>
</template>
<script>
import axios from 'axios'
import { useToast } from "vue-toastification";
export default {
name: 'Project',
setup() {
// Get toast interface
const toast = useToast();
return { toast }
},
data() {
return {
project: [],
errors: [],
}
},
mounted() {
this.getItemsProjects()
},
props: {
slug: {
type: String,
required: true,
},
},
methods: {
async getItemsProjects() {
this.$store.commit('setIsLoading', true)
axios
.get(`/api/v1/projectdetail/${this.slug}`)
.then(response => {
this.project = response.data
console.log(this.project)
})
.catch(error => {
console.log(error)
})
this.$store.commit('setIsLoading', false)
},
}
}
</script>
and my router:
import { createRouter, createWebHistory } from 'vue-router'
import store from '../store'
import HomeView from '../views/HomeView.vue'
import Signup from '../views/SignupView.vue'
import Login from '../views/LoginView.vue'
import Dash from '../views/DashView.vue'
import Myacc from '../views/MyAccView.vue'
import Profile from '../views/ProfileView.vue'
import Projects from '../views/ProjectsView.vue'
import ProjectDetail from '../views/DetailProjectView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/signup',
name: 'signup',
component: Signup
},
{
path: '/login',
name: 'login',
component: Login
},
{
path: '/dash',
name: 'dash',
component: Dash,
meta: {
requiredLogin: true
}
},
{
path: '/myacc',
name: 'myacc',
component: Myacc,
meta: {
requiredLogin: true
}
},
{
path: '/profile',
name: 'profile',
component: Profile,
meta: {
requiredLogin: true
}
},
{
path: '/projects',
name: 'projects',
component: Projects,
meta: {
requiredLogin: true
}
},
{
path: '/project/:slug',
name: 'projectdetail',
component: ProjectDetail,
meta: {
requiredLogin: true,
}
},
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiredLogin) && !store.state.isAuthenticated) {
next('/login')
} else {
next()
}
})
export default router
how to fix this bug? thank you for advice.. im new in vue
edit

vuejs3 Uncaught (in promise) RangeError: Maximum call stack size exceeded

hello i am a vuejs newbie, what i want to do actually looks simple but i couldn't figure it out.
when a member logs in
both
I want "Dashboard.vue" to be loaded as well as "home.vue" to be loaded, I've done it somehow, but
"http://localhost/home"
when i write
I get the following error.
how can i solve this?
Uncaught (in promise) RangeError: Maximum call stack size exceeded
at pushWithRedirect
app.js
require('./bootstrap');
import {createApp} from 'vue';
import App from './App.vue'
import AdminRouter from './Admin/router';
createApp(App)
.use(AdminRouter )
.use(store)
.mount("#app");
App.vue
<template>
<div class="min-h-screen bg-gray-100">
<main>
<router-view v-slot="{ Component }">
<transition name="fade" mode="out-in">
<component :is="Component"/>
</transition>
</router-view>
</main>
</div>
</template>
router/index.js
import {createRouter, createWebHistory} from 'vue-router'
import routes from './routes.js'
import store from '../../store'
const router = createRouter({
history: createWebHistory(),
routes
})
router.beforeEach((to, from, next) => {
if (store.getters.user) {
if (to.matched.some(route => route.meta.guard === 'guest')) next({name: 'admin'})
else next();
} else {
if (to.matched.some(route => route.meta.guard === 'auth')) next({name: 'login'})
else next();
}
})
export default router;
routes.js
export default [
{
path: "",
component: () => import('../layout/Dashboard.vue'),
name: 'admin',
redirect: {name: 'home'},
meta: {guard: 'auth'},
children: [
{
path: "/",
component: () => import('../Views/Home.vue'),
name: "home",
meta: {guard: 'auth'}
},
{
path: "user",
component: () => import('../Views/User/UserList.vue'),
name: "user",
meta: {guard: 'auth'}
},
]
},
{
path: '/:pathMatch(.*)*',
redirect: '/home',
}
];

QUASAR: Redirection using "push" does not work

Good day. I have the following file "pages / Login.vue"
Here the form:
Simple form
<template>
<div>
<q-form #submit="btnlogin">
<q-input v-model="user" type="text" label="Usuario" />
<q-input v-model="pass" type="password" label="ContraseƱa" />
<q-btn color="primary" label="Ingresar" type="submit"/>
</div>
</template>
<script>
import axios from 'axios'
import { ref } from 'vue'
import { useQuasar } from 'quasar'
import router from 'src/router/index'
export default {
setup () {
const $q = useQuasar()
const user = ref(null)
const pass = ref(null)
const btnlogin = async () => {
axios.post("http://localhost:3050/loginQuest",{
uss : user.value,
pww : pass.value
})
.then(resp=>{
if(resp.data=="ERROR"){
$q.notify({
type:'negative',
message:'Datos incorrectos!'
})
}
else{
router().push({ path: '/' })
}
})
}
return {
user, pass, btnlogin
}
}
}
</script>
When the verification is successful, the address bar changes to http://localhost: 8080 but the content does not change and the Login.vue form continues to be displayed on the screen.
it sends me to the path but does not change the content, but if I refresh the page it shows the correct content
This is my router/routes.js:
const routes = [
{
path: '/',
component: () => import('layouts/MainLayout.vue'),
children: [
{ path: '', component: () => import('pages/Index.vue') },
{ path: '/form', component: () => import('pages/Form.vue') },
{ path: '/user', component: () => import('pages/Usuarios.vue') },
{ path: '/prueba', component: () => import('pages/Prueba.vue') },
{ path: '/facturas', component: () => import('pages/Facturas.vue') },
],
},
{ path: '/login', component:()=> import('pages/Login.vue')},
{ path: '/:catchAll(.*)*', component: () => import('pages/Error404.vue')}
]
export default routes
I changed the quasar.conf.js setting in the "vueRouterMode" section from hash to history. I hope you can help me, I'm stuck in it. Thank you!
Your script should look something like this:
<script>
import axios from 'axios'
import { ref } from 'vue'
import { useQuasar } from 'quasar'
import { useRoute } from 'vue-router' // <- import useRoute here
export default {
setup () {
const $q = useQuasar()
const router = useRouter()
const user = ref(null)
const pass = ref(null)
const btnlogin = async () => {
axios.post("http://localhost:3050/loginQuest",{
uss : user.value,
pww : pass.value
})
.then(resp=>{
if(resp.data=="ERROR"){
$q.notify({
type:'negative',
message:'Datos incorrectos!'
})
}
else{
router.push({ path: '/' }) // << router is an object, not a function
}
})
}
return {
user, pass, btnlogin
}
}
}
</script>
Is Posible that on you are created route on yout router.js or router/index.js a method for wraper router (if you show you router definition help to know it).
but I was a similar problem, I resolve it with:
let router: Router;
...
export default route(function ( ... ) {
if (router) {
return router;
}
....
router = createRouter({
... // your code
});
return router;
});
it require unique intanciated object router. It solve for me.

VueRouter this.$route.query always empty

I'm trying to get the query param code, but $route.query is always empty. I've used function mode per the docs. What is missing?
Router:
// use vue-router
import Router from 'vue-router'
Vue.use(Router)
// create router
const router = new Router({
routes: [
{
path: '/',
component: Home,
props: (route) => ({ code: route.query.code })
}
]
})
Home.vue
<template>
<div>
<Navbar />
<FlatHeader />
<v-content>
<ComingSoon />
<Changes />
<EmailSubscribe />
</v-content>
<AuthorizationModal />
</div>
</template>
<script>
import AuthorizationModal from './components/AuthorizationModal';
import FlatHeader from './components/FlatHeader';
import ComingSoon from './components/ComingSoon';
import Changes from './components/Changes';
import EmailSubscribe from './components/EmailSubscribe';
export default {
name: 'Home',
components: {
FlatHeader,
ComingSoon,
Changes,
EmailSubscribe,
AuthorizationModal
},
props: {
code: {
type: String,
default: null
}
},
methods: {
},
mounted() {
console.log(this.$route)
}
}
</script>
$route console output:
I resolved this by setting the mode on Router to 'history'.
Router:
// create router
const router = new Router({
mode: 'history', // add 'history' mode
routes: [
{
path: '/',
component: Home,
props: (route) => ({ code: route.query.code })
}
]
})

Vue Component Issue

I have this page I want to try out Vue Router with Vue Components. I cant figure out whats wrong. I am getting an error Uncaught TypeError: Cannot read property 'name' of undefined at this line const App = new Vue.extend({})
<body>
<div id="app">
<router-view></router-view>
</div>
<template id="foo"> <h1>This is homepage</h1> </template>
<template id="bar"> <h1>This is Bar page</h1> </template>
</body>
//Vue.js v1.0.28
<script src="{{ asset( 'js/vue.js' ) }}"></script>
// vue-router v0.7.13
<script src="{{ asset( 'js/vue-router.js' ) }}"></script>
<script>
const router = new VueRouter()
const App = new Vue.extend({})
router.map({
'/': {
component: {
template: '#foo'
}
},
'/bar': {
component: {
template: '#bar'
}
},
})
router.start(App, '#app')
</script>
</html>
What am I doing wrong?
EDIT:
Okay, I have managed to get this working.
const Foo = Vue.component('foo', { template: '#foo' });
const Bar = Vue.component('bar', { template: '#bar' });
Vue.use(VueRouter)
const router = new VueRouter()
router.map({
'/foo': {
component: Foo
},
'/bar': {
component: Bar
},
})
var App = Vue.extend({})
router.start(App, 'body')
What I need now is to extract those templates from index.blade.php into their own files like Foo.vue and Bar.vue. How do I do that?
I am using Webpack to compile assets.
You could try to use vue-router v.v2.2.1 and you can check this official example https://github.com/vuejs/vue-hackernews-2.0 and here router code:
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import { createListView } from '../views/CreateListView'
import ItemView from '../views/ItemView.vue'
import UserView from '../views/UserView.vue'
export default new Router({
mode: 'history',
scrollBehavior: () => ({ y: 0 }),
routes: [
{ path: '/top/:page(\\d+)?', component: createListView('top') },
{ path: '/new/:page(\\d+)?', component: createListView('new') },
{ path: '/show/:page(\\d+)?', component: createListView('show') },
{ path: '/ask/:page(\\d+)?', component: createListView('ask') },
{ path: '/job/:page(\\d+)?', component: createListView('job') },
{ path: '/item/:id(\\d+)', component: ItemView },
{ path: '/user/:id', component: UserView },
{ path: '/', redirect: '/top' }
]
})