2

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>

2 Answers 2

3

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

Sign up to request clarification or add additional context in comments.

1 Comment

This is awesome. I had been searching for a while as to why my view wasn't updating with the route. Thanks for providing a more specific usage example as well
0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.