Vue router button not clickable because setup is incorrect - javascript

I'm trying to setup Vue router for the first time and I'm running into trouble.
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Services from '../components/Services'
import App from '../app'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'App',
component: App
},
{
path: '/services',
name: 'Services',
component: Services
}
]
})
app.vue
<template>
<div id='app'>
<Navigation></Navigation>
<div class="Site-content">
<router-view></router-view>
</div>
<Footer></Footer>
</div>
</template>
<script>
import Services from "../javascript/components/Services";
import Footer from "../javascript/components/Footer";
import Navigation from "../javascript/components/Navigation";
export default {
components: {
Footer,
Navigation,
Services
},
data: function () {
return {
message: "Welcome to Ping Party From Vue!"
}
}
}
</script>
Navigation.vue
<template>
<div id="navigation">
<nav v-bind:class="active" v-on:click>
Home
Projects
<router-link to="/services">Services</router-link>
Contact
</nav>
</div>
</template>
<script>
import Services from './Services'
export default {
data () {
return { active: 'home' }
},
methods: {
makeActive: function(item) {
this.active = item;
}
}
}
</script>
That vue-router option is not working in my navigation. It shows up on the page but it's not clickable and I'm getting this error in the console.
ERROR
Unknown custom element: <router-link> - did you register the component
correctly? For recursive components, make sure to provide the "name"
option.
found in
---> <Navigation> at app/javascript/components/Navigation.vue
<App> at app/javascript/app.vue
<Root>
Unknown custom element: <router-view> - did you register the component
correctly? For recursive components, make sure to provide the "name"
option.
found in
---> <App> at app/javascript/app.vue

Make sure to register your router with your Vue instance.
So in your
import router from './router'
new Vue({
el: '#some-element'
router, // This line is important
render: h => h(App)
})

Related

How to make the vue router link connect to the vue component?

I am very new to the Vue framework, as well as Javascript, but am currently building a site using Vue and I want to have some links at the top of my site that the user can navigate to. I have tried using the Vue Router (https://router.vuejs.org/guide/#javascript) in order to make these links. At this point, I just want to make a little 'About Us' section that the user can navigate to. But, despite the URL changing accordingly to 'localhost:8080/#/about_us', the Vue component that I have associated with the link will not show up.
I have structured my code in the main.js as such:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
Vue.config.productionTip = false
export const eventBus = new Vue();
Vue.use(VueRouter);
const AboutUs = {template: '<div>about_us</div>'};
const route = [{path:'/about_us', component: AboutUs}];
const router= new VueRouter({route});
new Vue({
render: h => h(App),
router
}).$mount('#app')
And then I have my app.vue designed as (note: I reduced much of the code to its essentials for brevity):
import AboutUs from './components/AboutUs.vue'
import { eventBus } from './main.js'
export default {
data(){
return {
films: []
}
},
components: {
"about-us": AboutUs
},
mounted(){
fetch('https://ghibliapi.herokuapp.com/films')
.then(res => res.json())
.then(films => this.films = films)
.catch(error=> console.log(error))
}
}
</script>
body {
background-color: deepskyblue;
}
<h1>Ghibli Fandom Extravaganza</h1>
<nav>
<li><router-link to="/about_us">About us </router-link></li>
<router-view></router-view>
</nav>
<p>List of Ghibli Movies: <films-list :films="films"/></p>
<film-detail />
At this point, my AboutUs component is only a very basic Vue that shows some information about the site in some simple HTML tags. But although the link is active and does work, the information from the Vue is not displayed, while the other Vue components continue to show, which indicates that maybe they are not connected? I have tried to follow the tutorial in the Vue Router site, but I don't think that I understand the mechanics of how the code actually works. Can anybody recommend me any corrections?
UPDATE:
Here is the code to my AboutUs.vue
<template>
<div>
<h1>This site is for examining the movies of Studio Ghibli</h1>
</div>
</template>
<script>
export default {
name: 'about-us'
}
</script>
<style scoped>
</style>
I think there is no need to import 'aboutus' component. You can just write like this <router-link to="about_us">About us </router-link>
and in the main.js declare the route like this
const route = [{path:'/about_us',name:'about_us', component: () => import("path to about us file")}];
The code samples you provided are a bit confusing, you should simply pass an imported view straight in to the component property of a router entry.
Where you have done:
const AboutUs = {template: '<div>about_us</div>'};
Replace that line with:
import AboutUs from './components/AboutUs.vue'
I can't figure out from your sample, when and what the relevance of components: {"about-us": AboutUs }, it is not needed.
Here is a sample of my setup:
router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'index',
component: () => import('../components/views/welcome')
},
{
path: '/about-us',
name: 'about-us',
component: () => import('../components/views/about-us')
}
]
const router = new VueRouter({
mode: 'history',
routes
})
export default router
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
App.vue
<template>
<v-app v-cloak>
<router-link :to="{ name: 'index' }">Welcome</router-link>
<router-link :to="{ name: 'about-us' }">About Us</router-link>
<router-view></router-view>
</v-app>
</template>
<script>
export default {
name: 'App'
}
</script>
components/views/about-us.vue
<template>
<div>This is the About Us page!</div>
</template>
<script>
export default {
name: 'about-us'
}
</script>
This sample uses History Mode
Other things to note
When routing, mounted is unreliable, instead you should place any fetch logic into it's own method when calling any :
methods: {
fetch () {
// https://github.com/axios/axios
axios.get('https://ghibliapi.herokuapp.com/films').then( ... )
}
}
Call this.fetch method in both beforeRouteUpdate and beforeRouteEnter instead of mounted, you can't even rely on created when it comes to views handled by vue-router.
Axios is suggested instead of native fetch because axios provides more functionality, features and browser compatibility.
In about-us.vue you add these Navigation Guards like so:
<template>
<div>This is the About Us page!</div>
</template>
<script>
export default {
name: 'about-us'
methods: {
fetch () {
axios.get('https://ghibliapi.herokuapp.com/films').then( ... )
}
}
// Will fire if you are already on the view but a parameter changes (dynamic routing)
beforeRouteUpdate(to, from, next) {
this.fetch()
next()
},
// Will fire when you enter the view
beforeRouteEnter(to, from, next) {
this.fetch()
next()
},
}
</script>
Both should be added, understand that they won't fire at the same time, only one of them will execute fetch once when relevant.
This will resolve any issues you would otherwise encounter with Dynamic Routing should you ever use them.
Folder Structure
src/
+ App.vue
+ main.js
+ router.js
+ vue.config.js
+ assets/
+ logo.png
+ components/
+ views/
+ welcome.vue
+ about-us.vue
Hope this clears up the setup requirement for you.

vue component not showing by router

I'm new to VueJs. I'm try to develop a theme using VueJs, I'm facing a problem by router, 'component not showing'. here is my code
Pagea.vue
<template>
<div>
<h1>Hello This is a test</h1>
</div>
</template>
<script>
export default {
name : "Pagea"
}
</script>
App.vue
<template>
<div id="app">
<router-link to="/">Go to Foo</router-link>
<router-link to="/Pagea">Go to Bar</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app',
components: {
Header,
Footer
}
}
</script>
main.js
import Vue from 'vue';
import App from './App.vue';
import VueRouter from 'vue-router';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-vue/dist/bootstrap-vue.css';
Vue.use(BootstrapVue);
Vue.use(VueRouter);
Vue.config.productionTip = false;
//Router
import Pagea from './components/Pagea.vue';
const routers = [
{
path: '/pagea',
name : 'Pagea',
component : Pagea
}
];
const router = new VueRouter({
routers,
mode : 'history'
});
new Vue({
router,
render: h => h(App)
}).$mount('#app')
There is no console error, but still to result. i don't know why the component or data not showing only empty page. please anyone could tell me what i did miss. As i early mansion that i'm new and still learning. Thank you.
The more sure, the issue is that your:
<router-link to="/Pagea">Go to Bar</router-link>
Should be:
<router-link to="/pagea">Go to Bar</router-link>
Since you have it declare as such in your router:
{
path: '/pagea', /* lower-case here */
name : 'Pagea',
component : Pagea
}
.....................................................................................................
However, if that doesn't solve it, then try the following:
Try the following and let me know if it did work for you.
Pagea.vue, remove the export and set the className to the div tag:
<template>
<div class="pagea">
<h1>Hello This is a test</h1>
</div>
</template>
Keep your vue files as clean an simple as you can.
Don't go mixing stuff there.
Remove the export out of your App.vue and make sure your to matches as case-sensitive.
In this case, you were indicating to go to '/Pagea' when your route was setup for '/pagea'
<template>
<div id="app">
<router-link to="/">Go to Foo</router-link>
<router-link to="/pagea">Go to Bar</router-link>
<router-view></router-view>
</div>
</template>
Move your router code into its own JS file:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Pagea from './components/Pagea.vue';
let routes = [
{
path: '/pagea',
name : 'pagea', /* Keep the name lowercase as in the className */
component: Pagea
}
];
export default new Router({
routes: ...
}
It will make your code cleaner and easier to maintain than everything in one file.
Then you can call your router.js in your main.js
import router from './router'
new Vue({
router,
render: h => h(App)
}).$mount('#app')

VueJS passing router to child component

How Can I pass router to my child component.
I have this as my router
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
export default function () {
const Router = new VueRouter({
mode: 'history',
routes : [
{
path: '/',
beforeEnter: ifAuthenticated,
component: () => {
return import('./../container/Index.vue')
}
},
{
path: '/login',
beforeEnter: ifNotAuthenticated,
component: () => {
return import('./../container/logn.vue')
}
}
],
})
return Router
}
Now my "/" (index.vue) route have a component Navbar and the Navbar have a logout button which logs out the user and redirect them to login page
Consider this to be my index.vue (with what I have done)
<template>
<q-layout>
<Navbar :thisInfo="routerAndStore"/>
</q-layout>
</template>
<script>
import Navbar from "./../components/navbar.vue";
export default {
name: "PageIndex",
components: {
Navbar
},
data() {
return {
routerAndStore: this
};
}
};
</script>
And then in my navbar.vue I have done something like this
<template>
<div class="nav-pages-main">
<a #click="logoutUser">
<h5>Logout</h5>
</a>
</div>
</template>
<script>
export default {
name: "navbar",
methods: {
logoutUser: () => {
return this.thisInfo.$store.dispatch("GOOGLE_PROFILE_LOGOUT").then(() => {
this.$router.push("/login");
});
}
},
props: {
thisInfo: {
type: Object
}
}
};
</script>
but this doesn't seem to be working (this is coming out to be undefined), So if someone can help me figure out how we can pass this to our child component
Please refer to Vue-Router official documentation here
Basically, in their use case, the main component (index.vue) take a router as argument and provide <router-view> in its template as placeholder for component that would be rendered based on the current route.
In your code, I see that you use it the other way around using router to render the main component.
routes : [
{
path: '/',
beforeEnter: ifAuthenticated,
component: () => {
return import('./../container/Index.vue')
}
},
...
]
Could you try it again using the right way described in the documentation and tell me the result?
Edit: According to the App.vue that you posted (assuming it's the app entry point) then you should provide router to the App component.
<template>
<div id="q-app"> <router-view/> </div>
</template>
<script>
import router from '/path/to/your/router';
export default { name: "App", router };
</script>
<style>
</style>
The full code for this can be found at Vue-Router example

Reinit javascript function when change view in vue js

I am kinda new in vue.js
I have a laravel app with vue.js. When hp is loading script also loading all elements are initialised (owl carousel, rev slider etc), but when i click other route contact or about and come back to hp the sliders or other related to js doesnt load .
routes.js
import VueRouter from 'vue-router';
import Home from './components/views/Home.vue';
import About from './components/views/About.vue';
import Contact from './components/views/Contact.vue';
let routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/contact', component: Contact },
{ path: '/notes', component: Notes }
];
export default new VueRouter({
routes,
linkActiveClass: 'active'
});
and app.js
import router from './routes';
import './components';
const app = new Vue({
el: '#app',
router
});
Is there a way to run the functions to load carousels etc each time i change view ?
On mounted trigger you can add your custom js for each component
<script>
export default {
mounted () {
}
}
</script>
if anyone stumbles upon this and still looking for a way to do it, this is how I managed to do this. wrap the <route-view/> in a <transition> which you can control with css and call a method on enter which calls the function you want.
this will call the function as soon as the component is loaded in the DOM on every route change
<transition name="slide" v-on:enter="reInitJS">
<router-view></router-view>
</transition>
<script>
//import the wanted function
import {init} from './main';
export default {
name: 'App',
methods: {
reInitJS(){
//call the function
init();
}
}
}
</script>

Undefined auth0 variables after routing in Vue

I am trying to add Auth0 to a colleagues Vue app while he's on holiday but I am struggling with creating a reusable navbar.
I followed a tutorial to get most of it setup: https://www.storyblok.com/tp/how-to-auth0-vuejs-authentication
My main.js
import Vue from 'vue'
import App from './App.vue'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import router from './router'
import Vuex from 'vuex'
import store from './Store'
import 'vue-awesome/icons'
import icon from 'vue-awesome/components/Icon'
import auth from './auth/auth'
import meta from 'vue-meta'
Vue.config.devtools = true;
Vue.config.productionTip = false;
Vue.config.errorHandler = function(err, vm, info) {
console.log("error: " + err);
console.log("error info: " + info);
};
Vue.use(BootstrapVue);
Vue.use(Vuex);
Vue.use(auth);
Vue.use(meta)
Vue.component('icon', icon);
new Vue({
router,
store: store,
render: h => h(App)
}).$mount('#app');
My App.vue:
<template>
<b-container>
<div id="app">
<navbar/>
<router-view/>
</div>
</b-container>
</template>
<script>
import WidgetBuilder from './components/WidgetBuilder/WidgetBuilder'
import Navbar from './components/NavBar.vue'
export default {
name: 'app',
components: {
Navbar: Navbar,
WidgetBuilder: WidgetBuilder
}
}
</script>
My Navbar:
<template>
<nav class="navbar navbar-dark bg-dark">
<a class="navbar-brand" href="/home">
<img src="https://a.storyblok.com/f/39898/1024x1024/dea4e1b62d/vue-js_logo-svg.png" width="40" height="40">
</a>
<div>
<img :src="$auth.user.picture" width="30" height="30">
<span class="text-muted font-weight-light px-2">{{$auth.name}}</span>
<button type="button" class="btn btn-outline-secondary btn-sm" #click="$auth.logout()">Logout</button>
</div>
</nav>
</template>
<script>
export default {
name: "navbar",
mounted() {
console.log(this.$router.params.auth)
},
}
</script>
My Callback:
<template>
<div class="callback"></div>
</template>
<script>
export default {
name: 'callback',
metaInfo: {
title: 'Callback',
},
mounted() {
// eslint-disable-next-line
this.$auth.handleAuthentication().then((data) => {
this.$router.push({ name: 'index' })
})
}
}
</script>
The problem is, after loggin and redirection my navbar cannot access the $auth object.
console:
error: TypeError: Cannot read property 'picture' of null
main.js?1c90:18 error info: render
main.js?1c90:17 error: TypeError: Cannot read property 'name' of null
main.js?1c90:18 error info: render
If i visit /home directly it works fine.
I'm not a really a JS dev and this ES6 stuff might as well be in Arabic, any of you vue experts out there point me in the right direction?
I've tried passing variables from the component like this:
<template>
<b-container>
<div id="app">
<navbar :auth="$auth"/>
<router-view/>
</div>
</b-container>
</template>
I've tried importing the service into my Navbar component (although that grates me)
I've tried different redirects, re-authenticating, re-mouting it in the navbar component with mounted() and data().
Im sure its something simple but im tearing my hair out, because as i said it totally alien to me at the moment.
I also followed the tutorial and had the same issue.
Since the navbar component is in my App.vue and not in my home component I found that the toolbar was being rendered before the response from auth0 was being set to localStorage (hence why a refresh on second load worked). Moving the navbar component inside the home component fixed the issue, but this was not ideal for me.
I used the event bus approach as recommended by a similar stack overflow question -
Re-render navigation bar after login on vuejs
auth.js
user: {
get: function() {
return JSON.parse(localStorage.getItem('user'))
},
set: function(user) {
localStorage.setItem('user', JSON.stringify(user))
this.$bus.$emit('logged', 'User logged')
}
}
navbar.vue
data() {
user: this.getUser()
}
created () {
this.$bus.$on('logged', () => {
this.user = this.getUser()
})
},
methods: {
getUser: function () {
var user = JSON.parse(localStorage.getItem('user'));
if (user === null) {
return ''
} else {
return user
}
}
},
Not the cleanest solution but it worked for me.
The object this.$auth is provided by a custom plugin from Auth0, in the guide you can read how to install and use it:
https://www.storyblok.com/tp/how-to-auth0-vuejs-authentication#setup-auth0--vuejs-auth-plugin

Categories

Resources