How to use router properly in VueJS - vue.js

I want to make my website multilingual, however when I write the code it is:
<a class="language-English row" href="recruit/en">
it will give a path as: http://localhost:8080/recruit/recruit/en
what if the code is:
<a class="language-English row" href="/en">
It takes me back to the home page again.... So what do I need to deal with here? Do I need further processing in the router.js file? Hope to get help ^^
Update:
So if I handle the router like this:
path: '/recruit',
name: 'Recruit',
component: () => import(/* webpackChunkName: "Recruit" */ '../views/Recruit/index.vue'),
children: [
{
path: "/recruit/:locale",
component: () => import(/* webpackChunkName: "Recruit" */ '../views/Recruit/index.vue'),
},
],
},
was it correct? and in a href tag how do i put it?

IMHO, there is no need for nested routing here:
{
path: '/recruit/:locale',
name: 'Recruit',
component: () => import('../views/Recruit/index.vue') // chunk name is set automatically.
},
Now in the template
<a class="language-English row" href="/recruit/en">English</a>
^
Don't miss the leading slash. If there is no leading slash, the router just joins the path to the current URL in the browser.

In this case you can use nested routes here.
Since your link is like this,
/recruit/recruit/en
In your routes.js file you can add,
{
path: "/recruit",
component: YourComponentHere,
children: [
{
path: "/recruit/:lang",
component: YourComponentHere,
},
],
},
And you can access :lang in your child component by using,
<template>
<h1>Language is {{ $route.params.lang }} </h1>
</template>
Or if you are using <script setup>,
<script setup>
import {useRoute} from 'vue-router';
const Router = useRoute();
</script>
<template>
<h1>Language is {{ Router.params.lang }} </h1>
</template>
Hope this will help.

Related

Why my router.push is ignoring part of my route path? VueJs

I'm new at Vue.js, and I'm trying to use router.push in my button to link it to my route, but, when I click it, it just ignores part of the string that I've put into it as part of the raw route path:
My button code:
<div style="text-align: center; justifyContent: center; display: flex;">
<Button label="Entrar" class="p-3 text-xl" style="width: 250px"
#click="$router.push('app/dashboard')"></button>
</div>
My router.js:
const routes = [
{
path: '/',
name:'login_page',
component: () => import('#/pages/Login')
},
{
path: '/app',
name: 'app',
component: App,
children: [
{
path: '/dashboard',
name: 'dashboard',
component: () => import('./components/Dashboard.vue')
}
]
}
];
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;
It works, but with this link (see image above) instead of localhost:8080/app/dashboard, could someone explain to me why it does work and why it's not going to localhost:8080/app/dashboard?
Nested routes
Note that nested paths that start with / will be treated as a root path. This allows you to leverage the component nesting without having to use a nested URL.

How do you build page within a folder in Vue?

I'm trying to have my URL as /social/fb/, i've tried looking online and documentation but can't find the answer to this simple question for the life of me.
My folder structure is:
Pages
-social
--fb
I have a social.vue file in pages which works fine as www.example.com/social but can't get www.example.com/social/fb. Any direction would be much appreciated.
Create social folder inside pages, then create fb.vue inside social folder.
This should work
I normally load the layout.vue from the router and treat everything else as a child which is passed though as a router-view, this then saves having an index.vue for each parent.
But you would always want to make a directory to contain the social pages. Then would be a case of simply adding to the router.js file.
layouts/template.vue
<template>
<router-view></router-view>
</template>
<script>
export default {
name: 'layout-template'
}
</script>
router.js
...
/*
* Social
*/
{
path: '/social',
component: () => import('./layout/template.vue'),
props: true,
// rendered inside <router-view>
children: [{
path: '/',
component: () => import('./pages/social/index.vue')
}, {
path: 'fb',
component: () => import('./pages/social/fb.vue')
}, {
path: 'twitter',
component: () => import('./pages/social/twitter.vue')
},
// or do something more dynamic
{
path: ':network', // accessible in component though `$route.params.network`
props: true, // makes accessible though `props: ['network']`
component: () => import('./pages/social/network.vue')
}]
},
...
./pages/social/index.vue - could show something /social homepage or change route to import('./pages/not-found.vue') instead.
./pages/social/network.vue
<template>
...
</template>
<script>
export default {
name: "page-social-network",
props: {
network: {
type: String,
default: ''
}
},
created() {
// or through
this.$route.params.network
}
};
</script>
<style lang="scss" scoped></style>
See: https://router.vuejs.org/guide/essentials/passing-props.html#boolean-mode
Otherwise is just standard vue pages

VueJS: How to make a nested router-view always render one of its routes?

TL:DR;Is it possible to make the router-view display a component without being on that component route ?
I am trying to imitate a carousel effect using router-view inside a child component.
The problem is that if I don't click on a router-link the router-view displays nothing.
I want to make on of the router-link be active when no other is in order to force the router-view to always display something.
App.vue with the top router-view:
<template>
<div id="app">
<router-view />
</div>
</template>
Router index.js:
const routes = [
{
path: "/",
name: "LandingPage",
component: LandingPage,
children: [
{
path: "/icons",
name: "Icons",
component: () => import(/* webpackChunkName: "about" */ "../components/portfolio/Icons.vue"),
},
],
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
scrollBehavior(to, savedPosition) {
if (to.hash) {
return {
selector: to.hash,
behavior: "smooth",
// offset: { x: 0, y: 75 }
};
} else {
return savedPosition;
}
},
});
LandingPage.vue:
<template>
<div class="page">
<Home></Home>
<About></About>
<Portfolio></Portfolio>
<Contact></Contact>
</div>
</template>
Portfolio.vue with the second router-view:
<template>
<section id="portfolio">
<ul>
<li v-for="slide in slider" :key="slide.path">
<router-link :to="`/${slide.link}`">{{ slide.text }}</router-link>
</li>
</ul>
<router-view />
</section>
</template>
As you can see I have only one route, which is / for the top router-view. This will render LandingPage.
I use hashes to navigate to the components inside LandingPage like so: <router-link :to="{ path: '/', hash: #${link.path} }">
I am trying to make the router-link :to="/icons" active and the Icons component render inside Portfolio's router-view when no other link from Portfolio is active.
It's important for it to remain active only inside Portfolio, because I have a Navbar with other router-link which go to various hashes inside LandingPage.
Is this even possible ?
If I understood, you want to show Icon when the route is '/'.
To define a default sub-route you need to have a route with an empty value (path:'').
Now if you don't want to change path use the 'alias' mechanism.
const routes = [
{
path: "/",
name: "LandingPage",
component: LandingPage,
children: [
{
path: "/icons",
alias: '',
name: "Icons",
component: () => import(/* webpackChunkName: "about" */ "../components/portfolio/Icons.vue"),
},
],
},
];
If alias doesn't meet your needs, define your sub-route twice(One by empty path second by '/icons')
You can also define /icons as the main route:
const routes = [
{
path: "/icons",
name: "LandingPage",
component: LandingPage,
children: [
{
path: "",
name: "Icons",
component: () => import(/* webpackChunkName: "about" */ "../components/portfolio/Icons.vue"),
},
],
},
];

nested router with lazy load not work propertly

I am new to Vue and want to navigate Product child routes, but it do not work & get NotFound page instead.
So my question is how to make it properly.
Or can someone give some details. Thanks
Online Editor
index.js
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/products',
component: () => import('../views/ProductPage.vue'),
children: productRouter
},
{
path: '/**',
component: NotFound
}
]
product.js
const productRouter = [
{
path: '',
name: 'products',
component: ProductPage
},
{
path: 'product/:id',
name: 'ProductDetails',
component: ProductDetails
},
{
path: '**',
component: NotFound
}
]
There are some little mistakes leading to your unexpected result.
In product.js router you should not prefix again with products since it is already in the scope of the /products route. The NotFound route is also not needed in this definition since the parent's NotFound already matches the same route patterns. You can rewrite the product router definition like below :
const productRouter = [
{
path: ':id',
name: 'ProductDetails',
component: ProductDetails
}
]
Then, in ProductList.vue, you should rewrite your router-link as below :
<router-link :to="`/products/${item.id}`"> {{ item.description }} </router-link>
Finally, in ProductPage.vue, you are missing the <router-view></router-view> needed to render your child routes as explained in the vue router documentation.. You could rewrite it like below :
<template>
<div id="productPage">
<h1>This is an Product Page</h1>
<ProductList :items="products"> </ProductList>
<router-view></router-view>
</div>
</template>

Update the parent data when user navigates to a specific route path

I'm new in VueJs, trying to set up a web application with Vue-route, and want to update the <header> style when user navigates to a specific URL, whether using "URL bar" directly or "navigation bar". In this case, we have a parent component that contains height_status data and some <router-links> on template.
I've done the "navigation bar" part with $emit technique and it works well but then I've tried to use it on created lifecycle hook in order to update the header whenever the /home route is created but event listener will not reach the parent_component.
How can I solve this? Is there a better way to do that?
Please see the code below:
Parent_component.vue
<template>
<div id="app">
<router-link to="/home" #height_size_ctrl="change_height">Home</router-link>
<router-link to="/about">About us</router-link>
<router-link to="/contact">Contact us</router-link>
<header :class="height_status ? 'head-h-s' : 'head-h-m'"></header>
<router-view/>
</div>
</template>
<script>
export default {
name: "Parent_component"
},
data() {
return {
height_status: false
}
},
methods: {
change_height(h) {
this.height_status = h
}
}
}
</script>
router.js
Vue.use(Router)
export default new Router({
routes: [
{
path: '/home',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: about
},
{
path: '/contact',
name: 'contact',
component: contact
}
]
})
home.vue
<template>
<h1>hello</h1>
</template>
<script>
export default {
name: 'home',
created: function(){
return this.$emit("height_size_ctrl", true)
}
}
</script>
You could also change the router:
router.js
{
path: '/home',
name: 'home',
component: Home,
meta: {
headerClass: 'head-h-s'
}
}
In your component
Parent_component.vue
computed: {
headerClass() {
return this.$route.meta.headerClass
}
}
Now headerClass is available in the template.
<header :class="headerClass"></header>
why don't you try class binding on route or route name something like:
<div :class="{'height_status': this.$route == '/home'}">Header</div>
or
<div :class="{'height_status': this.$route.name == 'Home'}">Header</div>
As #kcsujeet said, class binding is the good way we can do this. In this case we need to look at the condition this.$route.path. if value is equal to the /home select 'head-h-m, otherwise select .head-h-s.
<header class="head-sec" :class=" this.$route.path == '/home' ? 'head-h-m' : 'head-h-s'">
Also we're able to access other route defined properties using this.$route. I suggest take a look at the router.js file.
routes: [
{
path: '/home',
name: 'home',
component: Home
}