Search code examples
javascriptarraysvue.jscomputed-properties

Vue computed array appends values instead of rewriting


I have an array called contactDetails that keeps a list of different contacts points (e.g. phone number, social media handle, etc) of the user. The available contact platforms are predefined in a list. I have a computed value that keeps track of which platforms the user has not added as a contact detail yet. The computed array is used in a select field for the user to choose from when creating a new contact detail.

new Vue({
    el: '#app',
    data() {
        return {
            platforms: [
                {
                    text: 'WhatsApp',
                    value: 1,
                },
                {
                    text: 'Call',
                    value: 2,
                },
                {
                    text: 'Email',
                    value: 3,
                },
                {
                    text: 'LinkedIn',
                    value: 4,
                },
                {
                    text: 'TikTok',
                    value: 5,
                },
                {
                    text: 'Twitter',
                    value: 6,
                },
            ],
            contactDetails: [],
        },
        onAddContactDetails() {
            var selectedPlatform = this.platforms.find(obj => {
                return obj.value == this.platformId
            })

            var newContact = {
                platform: selectedPlatform.value,
                platformName: selectedPlatform.text,
                channel: this.channel,
                priority: this.contactPriorityId
            }
            this.contactDetails.push(newContact)
            this.updatePriority(newContact, this.contactDetails)

            this.platformId = null
            this.contactPriorityId = null
            this.channel = null

            this.platformList = null;
            this.isAddContact = false;
        },
        computed: {
            platformList() {
                var list = [];
                if (this.contactDetails.length == 0) {
                    return this.platforms;
                } else {
                    list = this.platforms;
                    for (var i = 0; i < this.contactDetails.length; i++) {
                        var id = this.contactDetails[i].platform;
                        for (var j = 0; j < this.platforms.length; j++) {
                            if (this.platforms[j].value == id) {
                                list.splice(j, 1)
                            }
                        }
                    }
                }
                return list;
            },

Before adding a contact detail

This is how the dropdown looks like before adding a new contact detail.

However, my computed property updates, but instead of refreshing the list, the new list is appended onto the existing options, thus causing duplication.

After adding a new contact detail

The original list + the new list of contact details, which is supposed to be (full list - contacts that the user has already added)

I would like to know how to fix this, and if there is a better way of setting the options available left for the user in the dropdown menu. Thanks!


Solution

  • You are mutating this.platforms in the computed property; you should clone it first if you are going to mutate it:

    list = this.platforms.slice()
    

    I'm not sure what's causing the duplication though. You are only ever pushing to contactDetails and removing from platforms.

    Your computed property can be simplified quite a bit:

    computed: {
      platformList() {
        // Filter platforms
        return this.platforms.filter(platform =>
          // Include this platform if there is no contact detail using that platform
          !this.contactDetails.some(contact =>
            contact.platform === platform.value
          )
        )
      }
    }