Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

stwilson's avatar

Vue: TypeError: Cannot read property of undefined.

My data works fine and populates the template, however I get warning: vue.js:2215 TypeError: Cannot read property 'short_name' of undefined

This seems to result from my computed variable countryName defined as this.countries[this.selected].short_name. I've tried declaring data: and props: short_name and inside of the country object; nothing I try solves the warning.

<script>
Vue.config.devtools = true;
Vue.config.debug = true;
Vue.component('mark-country-selector', {
    template: '#mark-country-template',
    data: function() {
        return {
            selected: 'US',
            countries: {}
        };
    },
    computed: {
            : function() {
        return this.countries[this.selected].short_name
        }
    },
    created: function() {
        this.fetchCountries();
    },
    methods: {
        fetchCountries: function() {
            this.$http.get('api/countries', function(countries) {
                this.countries = countries;
            }.bind(this));
        }
    }
});

new Vue({
    el: '#mark-country'
});
</script>

Console warnings:

vue.js:2212 [Vue warn]: Error when evaluating expression "function () {
        return this.countries[this.selected].short_name
        }". exports.warn @ vue.js:2212Watcher.get @ vue.js:6030Watcher.evaluate @ vue.js:6214computedGetter @ vue.js:8826(anonymous function) @ VM346954:3Watcher.get @ vue.js:6024Watcher @ vue.js:5992Directive._bind @ vue.js:9556linkAndCapture @ vue.js:2507compositeLinkFn @ vue.js:2485exports._compile @ vue.js:9267exports.$mount @ vue.js:10456exports._init @ vue.js:8443MarkCountrySelector @ VM346952:2build @ vue.js:5723mountComponent @ vue.js:5643(anonymous function) @ vue.js:5608(anonymous function) @ vue.js:5623cb @ vue.js:542exports._resolveComponent @ vue.js:9858resolveComponent @ vue.js:5625setComponent @ vue.js:5607bind @ vue.js:5564Directive._bind @ vue.js:9529linkAndCapture @ vue.js:2507compositeLinkFn @ vue.js:2485exports._compile @ vue.js:9268exports.$mount @ vue.js:10456exports._init @ vue.js:8443Vue @ vue.js:80(anonymous function) @ aircraft:864
vue.js:2215 TypeError: Cannot read property 'short_name' of undefined
    at MarkCountrySelector.countryName (aircraft:849)
    at Watcher.get (vue.js:6024)
    at Watcher.evaluate (vue.js:6214)
    at MarkCountrySelector.computedGetter [as countryName] (vue.js:8826)
    at MarkCountrySelector.eval (eval at exports.compileGetter (vue.js:6876), <anonymous>:3:9)
    at Watcher.get (vue.js:6024)
    at new Watcher (vue.js:5992)
    at Directive._bind (vue.js:9556)
    at linkAndCapture (vue.js:2507)
    at compositeLinkFn (vue.js:2485)
0 likes
4 replies
bedakb's avatar

I think It's because Vue doesn't wait for response from server (AJAX fetching data), so at the one moment countries object is empty.

What you could try is wrap your template content into div and set v-if="countries" attribute.

erikverbeek's avatar
Level 9

@bedakb That wouldn't work since countries is already defined as an empty object in data v-if would still return true.

@stwilson if 'us' is always the default for selected you could add it to the countries object in data.

data: function() {
        return {
            selected: 'US',
            countries: { 'US' : 'United States' }
        };
    },

That way it will always have that default to show before your countries have been fetched.

Alternatively you could go with

if(typeof this.countries[this.selected] !== 'undefined'){
    return this.countries[this.selected].short_name;
}
1 like
stwilson's avatar

Thanks for the reply. I tried that, still the same. (referring to bedakb's suggestion)

Here is a simplified model of what I'm trying to do. I hard coded a small data sample:

JS Bin

stwilson's avatar

Thank you for supporting the learning. It's clear to me now.

Please or to participate in this conversation.