Join the Stack Overflow Community
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I've been trying to reproduce the button behavior that I've here, but with a different implementation. Basically, I'm trying to use Vuex instead of vue-i18n.js for internationalization purposes.

I now have the following code block, the purpose of which is to create language states and perform a XMLHttpRequest (for the .json files storing the various translations):

Vue.use(Vuex);
var storelang = new Vuex.Store({
    state: {
        lang: {}
    },
    mutations: {
        LANG: function (state, ln) {
            function loadJSON(callback) {
                var xobj = new XMLHttpRequest();
                xobj.overrideMimeType("application/json");
                xobj.open('GET', '../resources/i18n/' + ln + '.json', true);
                xobj.onreadystatechange = function () {
                if (xobj.readyState == 4 && xobj.status == "200") {
                        callback(xobj.responseText);
                    }
                };
                xobj.send(null);
            }

            loadJSON(function (languageJSON) {
                state.lang = JSON.parse(languageJSON);
            })
        },
        strict: true
    }
});

var mix = Vue.mixin({
    computed: {
        lang: function () {
        return storelang.state.lang;
        }
    }

});

On my component constructor (created and initialized in the root Vue instance), I've the following:

components: {
        lang: {
            template: '<button type="button" class="btn btn-info" @click.prevent=activate(lang.code) @click="setActiveLang" v-show="!isActive">{{ lang.code }}</button>',
            props: [
                'active',
                'lang'
            ],
            computed: {
                isActive: function() {
                    return this.lang.code == this.active.code
                }
            },
            methods: {
                activate: function(code) {
                    storelang.dispatch('LANG', code);
                },
                setActiveLang: function() {
                    this.active = this.lang;
                }
            },
            ready: function() {
                storelang.dispatch('LANG', 'en'); //default language
            }
        }
    }

On my root Vue instance's data object, I've added the following:

langs: [{
    code: "en"
}, {
    code: "fr"
}, {
    code: "pt"
}],
active: {
    "code": "pt"
}

And finally, on my html:

<div v-for="lang in langs">
    <p>
        <lang :lang="lang" :active.sync="active"></lang>
    </p>
</div>

I cannot figure out what I'm doing wrong here.


UPDATE

Here's a JsFiddle (I've exchanged the XMLHttpRequest request for json arrays). Also, this is a working example, but the language selector buttons do not hide when the respective language is selected, which is the opposite of what I want. Meaning that, I'm attempting to hide each individual language selector button when the user clicks it and selects the respective language (while showing the other language selector buttons).

share|improve this question
    
Could you be more specific about your problem? – nils Mar 23 at 11:27
    
I've updated the question with a couple more JsFiddles at the bottom and added further clarification. – pierrebonbon Mar 23 at 11:36
up vote 0 down vote accepted

The solution involves saving anactive state in the store, in addition to the lang state:

new Vuex.Store({
    state: {
        active: {},
        lang: {}

Adding an ACTIVE mutation:

ACTIVE: function(state, ln) {
        var langcode = 'en'
    //portuguese
    if (ln === 'pt') {
        langcode = 'pt'
    }
    //french
    if (ln === 'fr') {
        langcode = 'fr'
    }
  state.active = langcode
}

On the computed properties block, one also needs to add getter functions for the active state and return the langcode that is currently active:

Vue.mixin({
    computed: {
        lang: function() {
            return storelang.state.lang
        },
        enIsActive: function() {
            return storelang.state.active == 'en'
        },
        frIsActive: function() {
            return storelang.state.active == 'fr'
        },
        ptIsActive: function() {
            return storelang.state.active == 'pt'
        }
    }
})

Then, it is just a question of conditionally displaying each of the buttons on the component template by adding v-show="!enIsActive", v-show="!frIsActive", etc.:

var langBtn = Vue.extend({
template: '<button type="button" class="btn btn-info" @click.prevent=activate("en") v-show="!enIsActive">en</button><button type="button" class="btn btn-info" @click.prevent=activate("pt") v-show="!ptIsActive">pt</button><button  type="button" class="btn btn-info" @click.prevent=activate("fr") v-show="!frIsActive">fr</button>',

Finally, on the activate method, adding a new line to change the active state when the user clicks a button:

methods: {
    activate: function(x) {
      storelang.dispatch('LANG', x)
      storelang.dispatch('ACTIVE', x)
    }
  }, 

The full working code here.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.