2

I think this is a fairly common problem. You fetch a list from an api, and then you display that list via

<div v-for="item in items">
    <checkbox v-model="item.checked">
</div>

Now My question is about the checked property. when iterating over a list of undefined length, of unknown keys, it seems the checked property has to be created and attached to the item object like so

computed: {
    items () {
        var newList = Object.assign([], this.rootList) // shallow clone the api list
        for (var i of newList) {
            i.checked = false
            // or
            Vue.set(i, 'checked', false)
        }
        return newList
    }

However this is not making my checkbox reactive. But more importantly, this way of adding new properties to the rootList object clone, is this the best practice? and if so, why is this not reactive? Even when using Vue.set

2
  • Related: stackoverflow.com/questions/42248888/… Commented Jul 19, 2018 at 13:51
  • it shouldn't be necessary, the array of objects returned from a computed would work as long as the objects are reactive. Can you show how this.rootList is defined? Commented Jul 19, 2018 at 17:04

1 Answer 1

1

Computed properties are by default getter-only [...]

https://v2.vuejs.org/v2/guide/computed.html#Computed-Setter

Due to the limitations of modern JavaScript (and the abandonment of Object.observe), Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive.

https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

This might help: https://jsfiddle.net/eywraw8t/187063/

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <div v-for="item in items">
            <input type="checkbox" v-model="item.checked"> {{ item.name }}
        </div>
        
        <button @click="fetch">Fetch more items</button>
    </div>              
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    <script>
        new Vue({
            el: "#app",
            
            data: {
                items: []
            },
            
            methods: {
                fetch() {
                    let itemsFromApiResponse = [
                        { name: "Test 1" },
                        { name: "Test 2" },
                        { name: "Test 3" },
                    ];
                
                itemsFromApiResponse.forEach(item => this.items.push(Object.assign({ checked: false }, item)));
                }
            }
        })
    </script>
</body>
</html>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.