I am new to vuejs, i have my api in laravel having a route such as
Route::get('/get-song-details/{id}','SongsController#getSongDetails');. How do get this id in vue so that i can display only information about the selected song.
in the sample below, when i pass 1, i get information about song 1, and so on. how do i make it dynamic?
export default {
data(){
return {
songs : []
}
},
created(){
axios.get('/api/get-song-details/1')
.then(response => this.songs = response.data);
}
};
</script>
asumming you are using vue-router, the route component should be declared so:
routes: [
{ path: '/song/:id', component: Song }
]
then in your created method of Song component can get the id param:
created() {
axios.get('/api/get-song-details/' + this.$route.params.id)
...
}
All route params can be accessed by using this.$route.params.paramName in JS code or by using $route.params.paramName in template. paramName is the parameter name as defined in your router.
Related
I'm trying to create a feature where individuals can create Listings, and other users can submit an application. ATM I can't quite figure out how to get the ID from the URL of:
'http://localhost:3000/listings/2/'
I have a hunch that this needs Vue router and $route.params.id? Basically I want in my form.listing the ID of the listing in which users are applying to. In this case it would be '2'
My folder structure is .../listings/_id/index.vue
This is my backend for the user_applications model in DRF:
listing = models.ForeignKey(Listings, on_delete=models.CASCADE, default="1")
Here's the frontend: I was hoping I could use the props value in script, but it seems like it only works in template, oh well.
data: () => ({
form: {
role: null,
company: null,
status: "Pending"
// listing: listings.id
}
}),
props: ["listings"],
computed: {
...mapGetters(["loggedInUser"])
},
methods: {
submit() {
this.$axios
.post("/api/v1/apps/", this.form)
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
}
You are on the right track when thinking of using VueRouter. Lets say that your component name is Listing.
import VueRouter from 'vue-router';
import Listing form './path/to/ListingComponent.vue';
const router = new VueRouter({
routes: [
{
path: '/listing/:id',
component: Listing,
// return parms.id as listingId for the `Listing` component.
props: route => ({ listingId: route.params.id })
}
]
})
In this way you have listingId passed to the props of Listing.
Yes, it's as easy as this.$route.params.id. You can invoke $route.params.id directly in your template, without using this. Don't use arrow functions in your component, though! They strip out the value of this! Also, all props and data attributes are available on this as well. So this.listing and this.$route are available, not only in your template, but in your Vue component's methods and computed properties, as well.
Try this approach, instead:
data() {
return {
form: {
role: null,
company: null,
status: "Pending",
listing: this.listings.id
}
}
},
My Nuxt app loads a link and it's child view on the route http://127.0.0.1/user/:id. I put the API calls for the user in mounted hook of the router view.
If route id changes, mounted is not triggered anymore because the child view is already loaded. I ended up with solution - watch the $route.params.id and moved the API call from mounted to this watcher.
watch: {
$route() {
this.getRows()
}
}
Is there a better way to do this?
Solution 1
Force the reload when the route changes defining a :key for the <nuxt-child>, like this:
<nuxt-child :key="$route.fullPath"></nuxt-child>
Solution 2
Put the API call to load the user in a watch to the id coming from the URL instead to mounted, you can use immediate: true to call it in the fist load.
export default {
data() {
return {
user: null
}
},
asyncData({ params }) {
return {
id: params.id
}
},
watch: {
id: {
immediate: true,
handler(id) {
//Call the API to get the user using the id
}
}
}
}
In my vue SPA I have a simple router like this:
{path: '/page/:userId', name: 'user', component: user},
Which means an url like http://xxx.xxx/user/1 shows the component user having the content about user 1.
In case on the same page I have some link as
<vue-link :to="{name:'user', params={userId:3}}">
The router update only the URL but the content page (because it assumes the page is the same where I'm at)
My user content loads data using the url params in data and in watch too
data
userId: this.$route.params.userId || 1,
watch
watch: {
userId: function () {
return this.$route.params.userId || 1;
},
How to fix it without using router-view?
Thanks for any suggestion
If I correctly get your problem which is that you are not able to track your route change. You need to watch the route change, whenever your route changed on a same component it should do something.
watch: {
$route() {
this.updatePage(this.$route.params.userId)
}
},
methods: {
updatePage(param) {
// call api / do something
}
}
In VueJS im trying to setup a scenario where the component used is determined by the url path without having to statically map it.
e.g.
router.beforeEach(({ to, next }) => {
FetchService.fetch(api_base+to.path)
.then((response) => {
router.app.$root.page = response
// I'd like to specify a path and component on the fly
// instead of having to map it
router.go({path: to.path, component: response.pageComponent})
})
.catch((err) => {
router.go({name: '404'})
})
})
Basically, I'd like to be able to create a route on the fly instead of statically specifying the path and component in the router.map
Hope that make sense. Any help would be appreciated.
I think that what you're trying to archive is programmatically load some component based on the current route.
I'm not sure if this is the recommended solution, but is what comes to my mind.
Create a DynamicLoader component whit a component as template
<template>
<component :is="CurrentComponent" />
</template>
Create a watch on $route to load new component in each route change
<script>
export default {
data() {
return {
CurrentComponent: undefined
}
},
watch: {
'$route' (to, from) {
let componentName = to.params.ComponentName;
this.CurrentComponent = require(`components/${componentName}`);
}
},
beforeMount() {
let componentName = this.$route.params.ComponentName;
this.CurrentComponent = require(`components/${componentName}`);
}
}
</script>
Register just this route on your router
{ path: '/:ComponentName', component: DynamicLoader }
In this example I'm assuming that all my componennt will be in components/ folder, in your example seems like you're calling an external service to get the real component location, that should work as well.
Let me know if this help you
As par the documentation of router.go, you either need path you want to redirect to or name of the route you want to redirect to. You don't the component.
Argument of router.go is either path in the form of:
{ path: '...' }
or name of route:
{
name: '...',
// params and query are optional
params: { ... },
query: { ... }
}
so you dont need to return component from your API, you can just return path or name of route, and use it to redirect to relevant page.
You can find more details here to create named routes using vue-router.
Using the vue-router package, it is easy to match dynamic segments:
router.map({
'/user/:username': {
component: {
template: '<p>username is {{$route.params.username}}</p>'
}
}
})
However, I couldn't figure out how to use the value a component method, e.g.
router.map({
'/user/:username': {
component: {
ready: function() {
// How to access the param here?
alert($route.params.username);
}
}
}
})
How can I access the matched segment in the component method?
Is almost as what you posted
// inside your component
this.$route.params.username
The key is that in the template you don't need to refer to the this scope, but in methods you have to use it
The $route object is injected in every router maped compeonents , as per your case you would use the params method to get the key/value passed .
router.map({
'/user/:username': {
component: {
ready: function() {
// How to access the param
// use the scope 'this'
alert(this.$route.params.username);
}
}
}
})
for more info check out http://router.vuejs.org/en/api/route-object.html