[Vuejs]-Computed property not evaluating when component is loaded

0πŸ‘

βœ…

A computed property is supposed to return a value while your addMarkers does not return any value.

Furthermore, a computed property is only computed at the moment you require it. So the fact that it is not showing the markers at the creation of your component is that the computed property is never required.

However, when you open the dev tools, VueJS tries to evaluate that computed property and executes the code. And your code adds the markers, but it is not a computed property.

So you have different solutions here.

Either you try to force the evaluation of your computed property on the mounted hook:

mounted() {
    this.map = new Gmaps({
        div: '#results-map',
        lat: 0,
        lng: 0,
        zoom: 15
    });
    this.bounds = new google.maps.LatLngBounds();
    this.addMarkers
}

Or you make a method of your addMarkers and execute it whenever you want:

import Gmaps from 'gmaps';

export default {
    name: 'maps',
    props: {
        results: {
            type: Array,
            required: true
        }
    },
    data() {
        return {
            map: {},
            bounds: {}
        }
    },
    methods: {
        addMarkers() {
            this.results.forEach((result) => {
                if (result.latitude && result.longitude) {
                    var marker = this.map.addMarker({
                        lat: result.latitude,
                        lng: result.longitude,
                        title: result.name,
                        infoWindow: {
                            content: result.name
                        }
                    });
                }
                this.bounds.extend(marker.position)
            });
            this.map.fitBounds(this.bounds)
        }
    },
    mounted() {
        this.map = new Gmaps({
            div: '#results-map',
            lat: 0,
            lng: 0,
            zoom: 15
        });
        this.bounds = new google.maps.LatLngBounds();
        this.addMarkers()
    }
}

For example, if you want to rerender the markers when results is changed, you can use the watch property:

export default {
    ...
    watch: {
        results: {
            deep: true,
            handler () {
                this.addMarkers()
            }
        }
    }
}
πŸ‘€Hammerbot

0πŸ‘

You aren’t using the addMarkers computed property anywhere. I think you want to change that to a method instead, and call it during your mounted function.

πŸ‘€Matti Price

0πŸ‘

Since you want to react to results changing from outside your component:

  • Turn the addMarkers() computed property, into a watcher on results.

This will make sure the code is executed everytime the results prop changes.

Also, since you are running some DOM manipulation logic in your mounted() hook:

  • Wrap the logic of the results watch inside a Vue.nextTick() to make sure it is executed when the DOM is ready to be changed (aka after you configured <google-maps>):

Vue.nextTick(): Defer the callback to be executed after the next DOM update cycle. Use it immediately after you’ve changed some data to wait for the DOM update.

So, your watch would (which used to be addMarkers() computed property) becomes:

watch: {                                                                 // line changed
    results: {                                                           // line changed
        deep: true,                                                      // line changed
        handler () {                                                     // line changed
            Vue.nextTick(() => {                                         // line changed
                this.results.forEach((result) => {
                    if (result.latitude && result.longitude) {
                        var marker = this.map.addMarker({
                            lat: result.latitude,
                            lng: result.longitude,
                            title: result.name,
                            infoWindow: {
                                content: result.name
                            }
                        });
                    }
                    this.bounds.extend(marker.position)
                });
                this.map.fitBounds(this.bounds)
            });                                                         // line changed
        }                                                               // line changed
    }
},
πŸ‘€acdcjunior

Leave a comment