Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Watch $route.params.slug doesn't triggered vuejs

I'm trying to use watch property of vuejs to perform action when my $route.params.slug change, but it's seems doen't work...

My $route.params.slug actualy change when i click to my router-link but the watcher's not triggered...

There is my app.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Clients from './components/ClientsComponent'
import Slider from './components/SliderComponent'
import store from './store/store'

require('./bootstrap');

Vue.use(VueRouter)

const routes = [
    {path: '/references/clients', component: Slider, name: 'client'},
    {path: '/references/clients/:slug-:id', component: Slider, name: 'client.show'}
]

const router = new VueRouter({
    mode: 'history',
    routes
})

const app = new Vue({
    el: '#app',
    store: store,
    router,
    components: {
        Clients,
        Slider
    }
});

My store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    strict: true,
    state: {
        clients: {},
        clientsPacks: [],
        slides: {}
    },
    getters: {
        clients: function (state) {
            return state.clients
        },
        clientsPacks: function (state) {
            return state.clientsPacks
        },
        slides: function (state) {
            return state.slides
        }
    },
    mutations: {
        addClient: function (state, {clients}) {
            let obj = {}
            let array = []
            let arraysPack = []
            let arraysPacks = []
            clients.forEach(function (client) {
                array.push(client)
                obj[client.id] = client
            })
            for (let i = 0; i < Math.ceil(array.length/9); i++) {
                arraysPack = []
                for (let y = i*9; y < 9 + i*9; y++) {
                    if (y < array.length) {
                        arraysPack.push(array[y])
                    }
                }
                arraysPacks.push(arraysPack)
            }
            state.clients = obj
            state.clientsPacks = arraysPacks
        },
        addSlide: function (state, {slides}) {
            let obj = {}
            slides.forEach(function (slide) {
                obj[slide.pos] = slide
            })
            state.slides = obj
        }
    },
    actions: {
        loadClients: async function (context) {
            axios.get('/api/clients')
                .then((response) => {
                    context.commit('addClient', {
                        clients: response.data.clients
                    })
                })
                .catch((error) => {
                    console.log(error);
                    throw new Error(error)
                });
        },
        loadSlides: async function (context, slug) {
            axios.get('/api/slides/' + slug)
                .then((response) => {
                    context.commit('addSlide', {
                        slides: response.data.slides
                    })
                })
                .catch((error) => {
                    console.log(error);
                    throw new Error(error)
                });
        }
    }
})

And my Components

ClientsComponent.vue

<template>
    <section id="clients">
        <article class="col-md-6 mosaic">
            <div v-if="clientsPacks.length > 1" id="Carousel" class="carousel vertical slide" data-ride="carousel" data-interval="false">
                <!-- Wrapper for slides -->
                <div class="carousel-inner">

                    <div v-for="(clientsPack, index) in clientsPacks" class="item" :class="{ 'active': index === 0 }">
                        <div v-for="client in clientsPack" class="col-sm-4 mosaic-item client">
                            <router-link
                                :to="{
                                    name: 'client.show',
                                    params: {
                                        slug: slugify(client.title),
                                        id: client.id
                                    }
                                }">
                                <div class="embed-responsive embed-responsive-16by9">
                                    <div class="slide-image embed-responsive-item" :style="{ backgroundImage: 'url(\'/storage/' + client.logo_URL + '\')' }"></div>
                                </div>
                            </router-link>
                        </div>
                    </div>

                </div>

                <!-- Left and right controls -->
                <a class="left carousel-control" href="#Carousel" data-slide="prev">
                    <span class="fa fa-chevron-left"></span>
                    <span class="sr-only">Previous</span>
                </a>
                <a class="right carousel-control" href="#Carousel" data-slide="next">
                    <span class="fa fa-chevron-right"></span>
                    <span class="sr-only">Next</span>
                </a>
            </div>

            <div v-else>
                <div v-for="client in clients" class="col-sm-4 mosaic-item client">
                    <router-link
                        :to="{
                            name: 'client.show',
                            params: {
                                slug: slugify(client.title),
                                id: client.id
                            }
                        }">
                        <div class="embed-responsive embed-responsive-16by9">
                            <div class="slide-image embed-responsive-item" :style="{ backgroundImage: 'url(\'/storage/' + client.logo_URL + '\')' }"></div>
                        </div>
                    </router-link>
                </div>
            </div>
        </article>

        <article class="col-md-6">
            <router-view></router-view>
        </article>
    </section>
</template>

<script>
    import {mapGetters} from 'vuex'
    export default {
        props: {
            client: Number
        },
        computed: {
            ...mapGetters(['clients']),
            ...mapGetters(['clientsPacks'])
        },
        mounted () {
            this.$store.dispatch('loadClients')
        },
        methods: {
            slugify: function (value) {
                if (!value) return ''

                var slug = "";
                // Change to lower case
                var valueLower = value.toLowerCase();
                // Letter "e"
                slug = valueLower.replace(/e|é|è|ẽ|ẻ|ẹ|ê|ế|ề|ễ|ể|ệ/gi, 'e');
                // Letter "a"
                slug = slug.replace(/a|á|à|ã|ả|ạ|ă|ắ|ằ|ẵ|ẳ|ặ|â|ấ|ầ|ẫ|ẩ|ậ/gi, 'a');
                // Letter "o"
                slug = slug.replace(/o|ó|ò|õ|ỏ|ọ|ô|ố|ồ|ỗ|ổ|ộ|ơ|ớ|ờ|ỡ|ở|ợ/gi, 'o');
                // Letter "u"
                slug = slug.replace(/u|ú|ù|ũ|ủ|ụ|ư|ứ|ừ|ữ|ử|ự/gi, 'u');
                // Letter "d"
                slug = slug.replace(/đ/gi, 'd');
                // Trim the last whitespace
                slug = slug.replace(/\s*$/g, '');
                // Change whitespace to "-"
                slug = slug.replace(/\s+/g, '_');

                return slug;
            }
        }
    }
</script>

SliderComponent.vue

<template>
    <div id="MainCarousel" class="carousel move-carousel slide" data-ride="carousel">
        <!-- Indicators -->
        <ol class="carousel-indicators">
            <li v-for="slide in slides" data-target="#MainCarousel" data-slide-to="{ slide.pos - 1 }" :class="{ 'active': slide.pos == 1 }"></li>
        </ol>

        <!-- Wrapper for slides -->
        <div class="carousel-inner">
            <div v-for="slide in slides" class="item" :class="{ 'active': slide.pos == 1 }">
                <div class="embed-responsive embed-responsive-16by9">
                <div class="slide-image embed-responsive-item" :style="{ backgroundImage: 'url(\'/storage/' + slide.image_URL + '\')' }"></div>
                </div>
                <div class="carousel-caption">
                <div class="col-xs-10 vcenter">
                    <h3>{{ slide.title }}</h3>
                    <p>{{ slide.caption }}</p>
                </div><!--
                --><div class="col-xs-2 logo vcenter">
                    <img v-if="slide.client_logo_URL" :src="'/storage/' + slide.client_logo_URL" width="100%">
                </div>
                </div>
            </div>
        </div>

        <!-- Left and right controls -->
        <a class="left carousel-control" href="#MainCarousel" data-slide="prev">
        <span class="fa fa-chevron-left"></span>
        <span class="sr-only">Previous</span>
        </a>
        <a class="right carousel-control" href="#MainCarousel" data-slide="next">
        <span class="fa fa-chevron-right"></span>
        <span class="sr-only">Next</span>
        </a>
    </div>
</template>

<script>
    import {mapGetters} from 'vuex'
    export default {
        props: {
            slide: Number
        },
        computed: {
            ...mapGetters(['slides'])
        },
        mounted () {
            this.loadSlides ()
        },
        watch: {
            'this.$route.params.slug': function () {
                this.loadSlides ()
            }
        },
        methods: {
            loadSlides () {
                console.log(this.$route.params.slug)
                this.$store.dispatch('loadSlides', this.$route.params.slug)
            }
        }
    }
</script>

I google it since 3 hours and i'm going crazy with this so...

Thank's for help.

like image 829
ecavard Avatar asked Jan 02 '23 19:01

ecavard


1 Answers

You should watch $route.params.slug instead of this.$route.params.slug

  watch: {
            '$route.params.slug': function () {
                this.loadSlides ()
            }
  },
like image 90
ittus Avatar answered Jan 05 '23 05:01

ittus