WoJ
WoJ

Reputation: 29987

Why isn't a bound variable modified?

I have a problem changing the value of a bound variable in Vue (I am not sure whether this is due to my lack of knowledge of Vue, or of JavaScript in general, probably both).

The initialization of the Vue instance is done via the code below

var vm = new Vue({
    delimiters: ['<<', '>>'],
    el: "#index-container",
    data: {
        posts: [],
        tags: {},
    },
    methods: {
        switchAll: function(what) {
            console.log(what)
            console.log(JSON.stringify(this.tags))
            _.forEach(this.tags, function (v, k) {
                console.log(k)
                this.tags[k] = false
            })
            console.log(JSON.stringify(this.tags))
        }
    },
(...)

Further down the script, values of tags are set with a constuction like Vue.set(vm.tags, tag, true) to ensure reactivity. They are then used in constrictions such as

<div class="tag on" v-for="(content, name) in tags" v-show="tags[name]" v-on:click="tags[name] = false">

Clicking on this div does change the value of the relevant element of the Object tags (initialized previously).

So far everything works as expected.

The problem is in the method switchAll. When I use it with a similar v-on:click() element (switchAll(false) for instance), it gets fired up but the console output is the following:

false
{"hello":true,"world":true}
hello
world
{"hello":true,"world":true}

My problem is that the last line should be {"hello":false,"world":false}.

I tried to use this.tags[k] = false and this.tags.k = false (though both are supposed to be equivalent) and I believe that the issue I have is that (apologies for the wording, I am new to JS) the keys in this.tags are "bare" in my case, and not "quoted". What my operation does is to add a new key, this time "quoted" (but then this.tags.k = false should be fine, as k is either hello or world (without quotes).

I am lost - what is wrong in my code, and why the inline code in the first (working) example of the div is fine?

Upvotes: 0

Views: 26

Answers (1)

Michał Sałaciński
Michał Sałaciński

Reputation: 2266

Not an expert in lodash, but it seems to be a problem with callback function creating new this. There are several ways around this problem, like:

  • If you're OK with ES6, use lambda functions - they won't create new this:

    _.forEach(this.tags, (v, k)=>{ console.log(k) this.tags[k] = false })

  • It can be useful to hold your this inside some method-wide variable:

    var vm = this; _.forEach(vm.tags, (v, k)=>{ console.log(k) vm.tags[k] = false })

  • Use vanillaJS object loop:

    for (var k in this.tags) { vm.tags[k] = false }

Upvotes: 1

Related Questions