Reputation: 21
I am trying to link between VueJS components using vue-router's v-link
. When a link is clicked, the URL is updated, but the view data does not update unless the page is manually refreshed.
Some context for this example: a Tour has many Tour Objects, and Tour Objects need to link to previous/next Tour Objects.
Here's the route that represents a Tour Object:
'/tours/:tourId/objects/:objectId': {
name: 'tourObject',
component: tourObjectComponent
}
Full example:
var App = Vue.extend({});
var tourObjectData = [
{ id: "1", name: "Object A" },
{ id: "2", name: "Object B" },
{ id: "3", name: "Object C" },
{ id: "4", name: "Object D" },
{ id: "5", name: "Object E" },
];
var tourComponent = Vue.extend({
template: '#tourComponent',
data: function() {
return {
objects: [],
};
},
created: function() {
this.objects = tourObjectData;
},
});
var tourObjectComponent = Vue.extend({
template: '#tourObjectComponent',
data: function() {
return {
currIndex: null,
currObject: {},
prevObject: {},
nextObject: {},
};
},
created: function() {
this.currIndex = this.getCurrIndex();
this.currObject = this.getCurrObject();
this.prevObject = this.getPrevObject();
this.nextObject = this.getNextObject();
},
methods: {
// Get current object index within tour objects
getCurrIndex: function() {
for (var i = 0; i < tourObjectData.length; i++) {
if (tourObjectData[i].id === this.$route.params.objectId) {
return i;
}
}
},
// Get current object
getCurrObject: function() {
return tourObjectData[this.currIndex];
},
// Get previous object
getPrevObject: function() {
var prevIndex = this.currIndex > 0 ?
this.currIndex - 1 :
tourObjectData.length - 1;
return tourObjectData[prevIndex];
},
// Get next object
getNextObject: function() {
var nextIndex = this.currIndex < tourObjectData.length - 1 ?
this.currIndex + 1 : 0;
return tourObjectData[nextIndex];
},
},
});
var router = new VueRouter();
router.redirect({
// Start on Tour 1
'/': '/tours/1'
});
router.map({
// Tour
'/tours/:tourId': {
name: 'tour',
component: tourComponent
},
// Object within tour
'/tours/:tourId/objects/:objectId': {
name: 'tourObject',
component: tourObjectComponent
}
});
router.start(App, '#app');
<script src="https://cdn.jsdelivr.net/vue/0.12.10/vue.js"></script>
<script src="https://rawgit.com/vuejs/vue-router/dev/dist/vue-router.js"></script>
<script type="x-template" id="tourComponent">
<h1>Tour</h1>
<ul>
<li v-repeat="objects">
<a v-link="{name: 'tourObject', params: {tourId: 1, objectId: id}}">{{name}}</a>
</li>
</ul>
</script>
<script type="x-template" id="tourObjectComponent">
<a v-link="{name: 'tour', params: {tourId: 1}}">Back to Tour</a>
<h1>{{currObject.name}}</h1>
<ul>
<li><a v-link="{name: 'tourObject', params: {tourId: 1, objectId: prevObject.id}}">Previous Tour Object: {{prevObject.name}}</a></li>
<li><a v-link="{name: 'tourObject', params: {tourId: 1, objectId: nextObject.id}}">Next Tour Object: {{nextObject.name}}</a></li>
</ul>
</script>
<div id="app">
<router-view></router-view>
</div>
Upvotes: 2
Views: 4413
Reputation: 1178
For vuejs ^2, you can watch the route and trigger a change like this (in my case I had username parameter in my user routes):
watch:{
'$route' (to, from) {
if (to.params.username !== from.params.username) {
//update whatever
}
}
},
Dynamic Route Matching from documentation
Upvotes: 3
Reputation: 14393
From the doc, (and help from @svevil on the gitter channel):
route: {
data(transition) {
transition.next(DataObjectForCurrentRoute);
}
}
Also, you can use computed
properties, like so:
var App = Vue.extend({});
var tourObjectData = [
{ id: "1", name: "Object A" },
{ id: "2", name: "Object B" },
{ id: "3", name: "Object C" },
{ id: "4", name: "Object D" },
{ id: "5", name: "Object E" },
];
var tourComponent = Vue.extend({
template: '#tourComponent',
data: function() {
return {
};
},
computed: {
objects: function() {
return tourObjectData;
}
},
});
var tourObjectComponent = Vue.extend({
template: '#tourObjectComponent',
data: function() {
return {
currIndex: null,
currObject: {},
prevObject: {},
nextObject: {},
};
},
computed: {
currIndex: function() {
for (var i = 0; i < tourObjectData.length; i++) {
if (tourObjectData[i].id === this.$route.params.objectId) {
return i;
}
};
},
currObject: function() {
return tourObjectData[this.currIndex];
},
prevObject: function() {
var prevIndex = this.currIndex > 0 ?
this.currIndex - 1 :
tourObjectData.length - 1;
return tourObjectData[prevIndex];
},
nextObject: function() {
var nextIndex = this.currIndex < tourObjectData.length - 1 ?
this.currIndex + 1 : 0;
return tourObjectData[nextIndex];
},
},
});
var router = new VueRouter();
router.redirect({
// Start on Tour 1
'/': '/tours/1'
});
router.map({
// Tour
'/tours/:tourId': {
name: 'tour',
component: tourComponent
},
// Object within tour
'/tours/:tourId/objects/:objectId': {
name: 'tourObject',
component: tourObjectComponent
}
});
router.start(App, '#app');
<script src="https://cdn.jsdelivr.net/vue/0.12.10/vue.js"></script>
<script src="https://rawgit.com/vuejs/vue-router/dev/dist/vue-router.js"></script>
<script type="x-template" id="tourComponent">
<h1>Tour</h1>
<ul>
<li v-repeat="objects">
<a v-link="{name: 'tourObject', params: {tourId: 1, objectId: id}}">{{name}}</a>
</li>
</ul>
</script>
<script type="x-template" id="tourObjectComponent">
<a v-link="{name: 'tour', params: {tourId: 1}}">Back to Tour</a>
<h1>{{currObject.name}}</h1>
<ul>
<li><a v-link="{name: 'tourObject', params: {tourId: 1, objectId: prevObject.id}}">Previous Tour Object: {{prevObject.name}}</a></li>
<li><a v-link="{name: 'tourObject', params: {tourId: 1, objectId: nextObject.id}}">Next Tour Object: {{nextObject.name}}</a></li>
</ul>
</script>
<div id="app">
<router-view></router-view>
</div>
Upvotes: 0