1

I am using Vuejs for template and databinding. Here is my HTML:

<div id="message"></div>
<div id="items">
    <div v-show="list.length > 0">
        <button v-on="click: selectMode = true"
                v-show="!selectMode">Start Selection</button>
        <button v-on="click: selectMode = false" 
                v-show="selectMode">End Selection</button>
        <button v-on="click: selectAll">Select All</button>
        <button v-on="click: remove">Remove</button>
    </div>
    <ul>
        <list-item v-repeat="list"></list-item>
    </ul>
</div>
<script type="text/html" id="template">
    <li>
        <input type="checkbox" v-show="$parent.selectMode" 
               v-model="selected" name="checkbox" value="{{Id}}" />
        <label>{{Name}}</label>
    </li>
</script>

And JS:

var message = document.getElementById("message");
var items = [
    { Id: 1, Name: "Apple" },
    { Id: 2, Name: "Orange" },
    { Id: 3, Name: "Banana" },
    { Id: 4, Name: "Mango" }
];

var data = {
    list: items,
    selectedList: [],
    selectMode: false
}

var vue = new Vue({
    el: "#items",
    data: data,
    methods: {
        selectAll: function(){
            if(!this.selectMode){
                this.selectMode = true;
            }

            for(var i = 0; i < this.list.length; i++){
                this.list[i].$set("selected", true);
            }
        },
        remove: function(){
            var length = this.selectedList.length;
            if(length === 0){
                show("Nothing to remove");
                return;
            }

            while(length > 0){
                var index = this.selectedList.pop();
                this.list.splice(index, 1);
                length--;
            }
        }
    },
    components:{
        'list-item': {
            template: "#template",
            computed: {
                selected: {
                    get: function(){
                        return this.$parent
                            .selectedList
                            .indexOf(this.$index) > 0;
                    },
                    set: function(value){
                        show(this.Name + " " + (value ? "Selected" : "Deselected") + " at index: " + this.$index);
                        if(value){
                            this.$parent
                                .selectedList
                                .$add(this.$index);
                        }
                        else{
                            this.$parent
                                .selectedList
                                .$remove(this.$index);
                        }
                    }
                }
            }
        }
    }
});

function show(mess){
    message.innerHTML = mess;
    setTimeout(function(){
        message.innerHTML = "";
    }, 5000);
}

Vuejs duly binds the template with list, and items are listed as expected in <li> tags. The problem is computed property: selected. The setter of this property is triggered when the checkbox is clicked, however, if the property is set in code, the setter isn't called.

When "Start Selection" button is hit, checkboxes are visible for each item. When user clicks on checkbox, setter of computed selected property is invoked. However, if you press, "Select All" button, which sets selected property to true, checkboxes are visible, and they are duly checked, but setter of selected property isn't triggered, which is unexpected. Why isn't this working? Either I am missing something, or this is a bug in Vuejs.

Here is a link to fiddle: http://jsfiddle.net/dreamakshay/c76rwugz/5/. These are few things you can try.

Run > Click Start Selection > Tick Checkboxes (setter triggered) > Message in Div, and "Remove" will remove the selected items.

Run > Click Select All (all checked) > Press Remove > An unexpected error in Div "Nothing to remove", which shouldn't happen.

Any help is appreciated.

1 Answer 1

3

Seems you forget to add this line:

    selectAll: function(){
        if(!this.selectMode){
            this.selectMode = true;
        }

        for(var i = 0; i < this.list.length; i++){
            this.list[i].$set("selected", true);
            this.selectedList.push(this.list[i]); // This line
        }
    }
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Dewey. I do have this line in my original code. However, I seem to have misunderstood computed properties in Vuejs. I have solved the issue. But still I am marking your post as answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.