Vue Props values not passed in simple test - vue.js

I'm new using VUE and I was testing a simple vue-router but props are not working in this test.
Here the test on jsfiddle
<div id="app">Menu:
<router-link to="/">Home</router-link> |
<router-link to="/post">Post</router-link> |
<router-link to="/foo">Foo link comment</router-link>
<router-view></router-view>
</div>
const Home = { template: '<div class="page">Welcome to my Home <router-link :to="{name:\'foo\'}">this link</router-link></div>' }
const Foo = {
props:['comment', 'msg'],
template: '<div class="page">{{msg}} Here the comment:<hr><div v-html="comment"></div><hr>Go back to <router-link :to="{name:\'home\'}">home</router-link></div>' }
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', name:'home',component: Home },
{ path: '/foo', name:'foo', component: Foo }],
})
new Vue({
router,
el: '#app',
data: {
msg: 'Hello World',
comment : '<div class="comment">This is a <strong>bold</strong> link</div>'
}
})
And how to pass the router link in prop HTML code?

You need to add props property in routes attribute
{ path: '/foo', name:'foo', component: Foo , props: true}
Also you need to pass prop value in router-link
<router-link :to="{ name: 'foo',
params: { comment: comment,msg: msg }}">Foo link comment</router-link>

Related

How to pass Dynamic Props through Routes in Vue 3?

I can send static props via <router-link> like so:
parent-component:
<router-link :to="{name: 'child-component'}"></router-link>
child-component:
<template>
<h1>{{ test }}</h1>
</template>
<script setup>
import {defineProps} from "vue";
const props = defineProps({
test: String
})
</script>
router.js:
const router = createRouter({
routes: [
{path: "/child-component", name: "child-component", component: ChildComponent, props: {test: 'hello world'}},
]
});
This correctly displays hello world in the h1 element in child-component. But how do I pass a dynamic element, say a state or prop (parent) through the route?
I've tried:
<router-link :to="{name: 'child-component'}" :props="{test: 'did this come through?'}"></router-link>
or
<router-link :to="{name: 'child-component'}" :test="'did this come through?'"></router-link>
But I don't know what to put instead of hello world:
const router = createRouter({
routes: [
{path: "/child-component", name: "child-component", component: ChildComponent, props: {test: 'hello world'}},
]
});
Here it is,
Router link
<router-link
:to="{
name: 'child-component',
params: { id: id, name: name },
}" >test
</router-link>
// Id and name are dynamic value
route.js file
const router = createRouter({
routes: [
{path: "/child-component/:id/:name", name: "child-component", component: ChildComponent},
]
})
You can access the params at the child component
<span>Name: {{ $route.params.name }} Id: {{ $route.params.id }}
</span>

Vue: How to pass custom props and router props?

I'm trying to pass props from one page to another with a redirect. Here's the code for the redirect:
<router-link :to="{ name: 'shipment', params: { editedItems: getSelected() } }">
Edit Amount
</router-link>
And here's the original code for the route in router:
{
path: "/inventory/shipment",
name: "shipment",
props: { screen: "shipment" },
component: Inventory,
},
As can be seen, I want to also pass a set variable, being screen, all the time. The route, shipment, can be called with router-link or through other methods. I know by setting props: true on the route it allows me to get the props sent via the redirect, but it doesn't allow me to pass the screen prop if router-link isn't called. What I'm looking for is the best of both worlds, being able to send both props.
Side note: I know I can easily get the prop on the page by looking at the url, but learning how to do a method like this will be helpful in the future when I don't have an easy out.
With Vue router you can access both information (props and params), just use a different pattern to get it:
const MainView = {
template: `<div>MAIN VIEW: click on TO INVENTORY to see data passed</div>`
}
const Inventory = {
props: ['screen'],
computed: {
routeParams() {
return Object.entries(this.$route.params).map(e => {
return `${e[0]}: ${e[1]}`
}).join(', ')
}
},
template: `
<div>
INVENTORY<br />
prop: {{ screen }}<br />
editedItems: {{ $route.params.editedItems }}<br />
all params: {{ routeParams }}
</div>
`
}
const router = new VueRouter({
routes: [{
path: '/',
name: "main",
component: MainView
}, {
path: '/inventory/shipment',
name: "shipment",
props: {
screen: "shipment"
},
component: Inventory
}]
})
new Vue({
el: "#app",
router
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<router-link :to="{ name: 'shipment', params: { editedItems: 'someitem' } }">TO INVENTORY</router-link>
<router-link :to="{ name: 'main' }">TO MAIN</router-link>
<router-view></router-view>
</div>

vue-router navigate to the same route and re-run mounted hook

How can I naviagte to the current route using router-link and re-run mounted hook?
HTML
<!-- Include the library in the page -->
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-router"></script>
<!-- App -->
<div id="app">
<nav>
<router-link :to="{ name: 'home' }" exact>Home</router-link>
<router-link :to="{ name: 'about' }" #click.native.prevent="router.push({ name: 'about' })">About</router-link>
</nav>
<router-view :key="$route.fullPath"></router-view>
</div>
JS
console.clear()
console.log('Yes! We are using Vue version', Vue.version)
Vue.use(VueRouter)
const Home = {
template: `<h1>Home</h1>`,
}
const About = {
template: `<h1>{{new Date()}}</h1>`,
mounted(){
console.log('mounted')
}
}
const routes = [
{ path: '/', name: 'home', component: Home },
{ path: '/about', name: 'about', component: About },
]
const router = new VueRouter({
routes,
})
// New VueJS instance
var app = new Vue({
// CSS selector of the root DOM element
el: '#app',
// Inject the router into the app
router,
})
In the above example, if I navigate to 'About' it shows the timestamp from new Date and logs 'mounted'. However, if I'm already on /about, clicking the about link does nothing. I want to re-run the whole component lifecycle when clicking 'About', even if I'm already hit it.
You'll need to change the key in the <router-view> element whenever the user clicks your about page, that will force the mounted hook:
<template>
<div id="app">
<router-link #click.native="updateViewKey" :to="{ name: 'about' }">About</router-link>
<router-view :key="viewKey"></router-view>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
viewKey: 1
};
},
methods: {
updateViewKey() {
this.viewKey+=1;
}
}
};
</script>
Try this :
router.push({
name: 'routeName',
params: {
id: 'new value'
}
})

Pass an image as prop in a router-link tag

How can I pass an image as prop in a vue-router tag ?
I have :
<router-link :to="{path: '/details', query: {
name: 'item',
//...
}}">
</routerlink
while in my "details" component I have :
<template>
<img :src="url">
</template>
<script>
export default {
name:'child-img',
props:['url'],
data() {
return {
}
}
}
</script>
So it's a case of passing props to your route which you have to set up in your router.
const router = new VueRouter({
routes: [
{ path: '/details/:url', component: Details, props: true },
// ...
]
})
then when you use your route:
<router-link to="`/details/${url}`">Details</router-link>
In the above url is the dynamic element you would be passing to it. If it comes from a v-for loop it would be item.url or whatever you are v-for ing.
OR if you name your route you can pass a param like this:
const router = new VueRouter({
routes: [
{ path: '/details/:url', name: 'Details', component: Details, props: true },
// ...
]
})
then use it like this:
<router-link :to="{ name: 'Details', params: { url } }">
Details
</router-link>
You can read more here

Two Path with same route and same component - Vue js

I have two path with same component like this:
/:loc("-host") - should match /usa-host
/:loc/:sublocation("-host") - should match /usa/washington-host
how to achieve this using single named route in vue.js
You can use alias of path
const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})
Check in doc
const Home = { template: '<div>Home</div>' }
const Project = {
template: '<div>Project {{id}}</div>',
mounted(){
console.log(this.$route);
},
data: function () {
return {
id:this.$route.params.id||'',
}
}
}
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
component: Home
},
{
path: '/projects/:id?',
component: Project,
alias: '/project/:id'
}
]
})
new Vue({
router,
el: '#app'
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<router-link to="/">Home</router-link> |
<router-link to="/projects">projects</router-link> |
<router-link to="/project/1">project/1</router-link>
<router-view></router-view>
</div>
Also check fiddle : https://jsfiddle.net/nikleshraut/9sgk6yg4/1/
Note : Opening same component is not working by default, you need to use other trick. For just testing above fiddle, go home->/projects and home->/project/1 will work but /projects->/project/1 or /project/1->/projects will not work. To make it work do something like this : https://jsfiddle.net/nikleshraut/9sgk6yg4/
This is my solution.
Router:
Use ? to separate param from literal in route.
const router = new VueRouter({
routes: [
{ path: '/', component: Home },
{ path: '/:loc/:subloc?-host', component: Location },
{ path: '/:loc?-host', component: Location },
]
})
Component:
Set local variables from $route.params.
const Location = {
template: '<div>Location {{loc}} - {{ subloc }}</div>',
data: function () {
return {
loc: this.$route.params.loc,
subloc: this.$route.params.subloc,
}
},
}
Template:
Use :key="$route.fullPath" to ensure component re-creates each navigation.
<div id="app">
<router-link to="/">Home</router-link> |
<router-link to="/usa-host" >loc1</router-link> |
<router-link to="/usa/washington-host" >loc2</router-link>
<router-view :key="$route.fullPath"></router-view>
</div>
Fiddle here