Reputation: 75
I have a clone of Twitter, I added a real-time search there, but I can't figure out how to send the required ID to another component. So that i can load the page of selected user.
Flowchart to make it clearer:
There is example of my code:
<template>
<input type="search" placeholder="Search Twitter" v-model="search" />
<div v-if="search.length > 0">
<ul v-for="user in filteredUsers" :key="user.id">
<li @click="userPageLink(user.id)">
{{ user.firstName + " " + user.lastName }}
</li>
</ul>
</div>
</template>
<script>
computed: {
users() {
return this.$store.getters["user/user"];
},
filteredUsers() {
return this.users.filter(
(user) =>
user.firstName.toLowerCase().indexOf(this.search) !== -1 ||
user.lastName.toLowerCase().indexOf(this.search) !== -1
);
},
},
methods: {
userPageLink(id) {
const url = `${this.$route.path}/${id}`;
this.$router.push(url);
},
},
</script>
Something tells me that I'm doing something completely wrong, do I need to get the id from the url?
Upvotes: 1
Views: 2115
Reputation: 170
All other answers are right. I will write some code for future users that come to this question.
For your particular question, the answer from @kissu is enough. But you can complete your code in different ways.
So let's get into the code.
Let's assume we have this router code
{
path: 'user/:id',
name: 'user',
params: {id: 0} //no need to set this here
component: Component,
}
If you do a $router.push
parsing the params, the router should be able to change your :id
in the path for your desire path for example localhost:8080/user/12345
. The following code does the job.
this.$router.push({name: 'user', params: {id: '12345'}})
But you can tell to Vue Router that your params are props too. To achieve that you can change your router code to this
{
path: 'user/:id',
name: 'user',
props: true // see that we replace the params with props
component: Component,
}
the key props
means that you can work with params as they are props in your component. You can learn more about this here
Now in your component, you need to set those props
export default {
name: 'User',
components: {},
props: {
id: { // This is the param that we are putting in our url
type: Number,
default() {
return 0
}
},
},
data(){
return{
user: {}
}
},
created(){
this.fetchUser();
}
methods: {
fetchUser(){
if (this.id){
console.log(this.id)
}
}
}
}
When you create the component you will fetch the user if the id from the params exists he prints it.
This is a basic example of router implementation, but you can go further and hide the user id in the URL if you don't want to show it and parse it to the component, the downside of this approach is every time you reload the page that information is lost. But if you want to do that you just need to change your path
and your $router.push()
Router File
{
path: 'user/:name', // we change the id to name (can be anything)
name: 'user',
props: true
component: Component,
}
Route Push
this.$router.push({name: 'user', params: {id: '12345', name: 'Joe'}})
User Component
props: { // Both Params are present in $route but only name is in path
id: {
type: Number,
default() {
return 0
}
},
name: { // This is the param that we are putting in our url
type: String,
default(){
return ''
}
}
},
This way your user only see in his URL <nameWebSite>/user/joe
.
If you for any reason want to navigate from '/user/:id' to '/user/:id' and don't want to keep the navigation history I suggest you using $router.replace()
works the same way as $router.push()
but replace the current entry
I hope this answer helps you with more details and other people that come later with the same type of question.
Tip: If you want to avoid at all parse params throw your router you can check the Vuex
Upvotes: 4
Reputation: 46814
As explained in the official docs of vue-router
, the clean way of doing is:
router.push({ name: 'user', params: { userId } }) // -> /user/123
But your interpolation is good too, maybe not the most explicit way of writing it.
I don't see anything wrong with the code so far at least.
Upvotes: 2