Change component and update data (ajax) when vue-router item is clicked

1.6k views Asked by At

When a router item is clicked I want to refresh (or reload) the data and display the correct component. Pages.vue loads the menu and should display the correct page in it's <router-view></router-view>.

Then Page.vue is a sub-route which should load within it. When I click on a menu item the sub-page (and component) is not loading but the path (URL) in the browser is updating.

If I manually refresh the browser on that route the correct page, component and data displays. I can't get to load when I click on the menu link.

Pages.vue: https://github.com/jackbarham/vuejs-playground/blob/master/src/components/Pages.vue

<template>
    <div class="row">
        <div class="col-md-3 col-sm-3 col-xs-3">
            <div class="list-group sidebar">
                <router-link v-for="page in pages" class="list-group-item" :to="'/pages/' + page.slug">{{ page.menu_title }}</router-link>
            </div>
        </div>
        <div class="col-md-9 col-sm-9 col-xs-9">
            <keep-alive>
                <router-view></router-view>
            </keep-alive>
        </div>
    </div>
</template>

<script>
    export default {
        computed: {
            pages() {
                return this.$store.state.pages
            }
        },
        created() {
            this.$http.get('pages').then((response) => {
                this.$store.commit('setPages', response.body)
                console.log(response)
            }, (response) => {
                console.log("Error: " + response)
            })
        }
    }
</script>

Page.vue: https://github.com/jackbarham/vuejs-playground/blob/master/src/components/Page.vue

<template>
    <div>
        <vc-gig :content="content" v-if="content.type == 'gig'"></vc-gig>
        <vc-text :content="content" v-if="content.type == 'text'"></vc-text>
        <vc-news :content="content" v-if="content.type == 'news'"></vc-news>
        <vc-home :content="content" v-if="content.type == 'home'"></vc-home>
        <vc-image :content="content" v-if="content.type == 'image'"></vc-image>
        <vc-audio :content="content" v-if="content.type == 'audio'"></vc-audio>
        <vc-video :content="content" v-if="content.type == 'video'"></vc-video>
        <vc-gallery :content="content" v-if="content.type == 'gallery'"></vc-gallery>
        <vc-release :content="content" v-if="content.type == 'release'"></vc-release>
        <vc-forwarder :content="content" v-if="content.type == 'forwarder'"></vc-forwarder>
    </div>
</template>

<script>
    import Gig from './Pages/Gig.vue'
    import Text from './Pages/Text.vue'
    import News from './Pages/News.vue'
    import Home from './Pages/Home.vue'
    import Image from './Pages/Image.vue'
    import Audio from './Pages/Audio.vue'
    import Video from './Pages/Video.vue'
    import Gallery from './Pages/Gallery.vue'
    import Release from './Pages/Release.vue'
    import Forwarder from './Pages/Forwarder.vue'

    export default {
        components: {
            'vc-gig': Gig,
            'vc-text': Text,
            'vc-news': News,
            'vc-home': Home,
            'vc-image': Image,
            'vc-audio': Audio,
            'vc-video': Video,
            'vc-gallery': Gallery,
            'vc-release': Release,
            'vc-forwarder': Forwarder,
        },
        data() {
            return {
                content: [],
            }
        },
        methods: {
            getPage() {
                this.$http.get('pages/' + this.$route.params.pageSlug).then((response) => {
                    this.content = response.body
                    console.log(response)
                }, (response) => {
                    console.log(response)
                });
            }
        },
        changed() {
            console.log('changed')
        },
        created() {
            this.getPage()
        }
    }
</script>

I presume there is some way to watch for changes or clicks on the parent Pages.vue then reload and display the correct Pages.vue page?

So, click on a menu item in Pages.vue then display the correct component in Page.vue.

I've Github links to help see the project.

1

There are 1 answers

1
Taha Shashtari On BEST ANSWER

I guess the issue is that this.content is not updated when the current pageSlug changes.

So you can fix it simply by adding this watcher in your Page.vue like so:

watch: {
  '$route.params.pageSlug' () {
    this.getPage()
  }
},

I hope this fixes it.