Cyril N.
Cyril N.

Reputation: 39859

Keeping track of added element in an array?

I'm playing around with vue.js and the .vue components, and as newbie, I'm wondering how can I keep track of the element I add in the array.

The situation is the following :

  1. The user add a new element from a form
  2. When he submit, the data are automatically added to a ul>li element, and a POST request is made to the API
  3. When the POST is done, I want to update the specific li with the new data from the server.

The thing is, I can not target the last li because the server can take time to process the request (he do a lot of work), so the user may have added 1, 5, 10 other entries in the meantime.

So how can I do ?

Here's my code so far :

<template>
    <form method="post" v-on:submit.prevent="search">
        <input type="text" placeholder="Person name" required v-model="name" v-el="nameInput" />
        <input type="text" placeholder="Company" required v-model="company" v-el="domainInput" />
        <input type="submit" value="Search" class="btn show-m" />
    </form>
    <ul>
        <li transition="expand" v-for="contact in contacts">
            <img v-bind:src="contact.avatar_url" width="40px" height="40px" class="cl-avatar" />
            <div class="cl-user">
                <strong class="cl-name">{{contact.name}} <span class="cl-company">{{contact.company}}</span></strong>
            </div>
        </li>
    </ul>
</template>

<script>
export default {
    data () {
        return {
            contacts: [],
            name: null,
            company: null
        }
    },
    methods: {
        search: function (event) {
            this.$http.post('/search', {
                name: this.name,
                company: this.company
            }).then(function (xhr) {
                // HERE ! How can I target the exact entry ?
                this.contacts.unshift(xhr.data)
            })

            this.name = ''
            this.company = ''

            this.contacts.unshift({'name': this.name, 'company': this.company})
        },
    }
}
</script>

Thank you for your help ! :)

Upvotes: 0

Views: 187

Answers (2)

Cyril N.
Cyril N.

Reputation: 39859

I finally found a working solution : I use a component instead of <li /> for each entries, and manage the state of these inside the component :

<ul>
    <contact-entry v-for="contact in contacts" v-bind:contact="contact"></contact-entry>
</ul>

That way, when I add a new entry in the array (described above), a new instance of the component contact-entry is made.

Inside that component, I did the following :

<script>
export default {
    props: ['contact'],
    created: function () {
        if (this.contact.id === undefined) { // If it's a new contact
            this.$http.post('search/name', { // I do the post here
                name: this.contact.name,
                domain: this.contact.company.name
            }).then(function (xhr) {
                this.contact = xhr.data // This will update the data once the server has replied, without hassle to find the correct line
            })
        }
    }
}
</script>

That's it ! :) In the parent's component, I removed the xhr request and simplified the method to :

<script>
export default {
    data () {
        return {
            contacts: [],
            name: null,
            company: null
        }
    },
    methods: {
        search: function (event) {
            this.name = ''
            this.company = ''

            this.contacts.unshift({'name': this.name, 'company': this.company})
        }
    }
}
</script>

Upvotes: 0

Jeff
Jeff

Reputation: 25221

If you know that the name and company fields are unique you could search through the array to find it... otherwise you can just wait to append it to the array until the return function:

    search: function (event) {
        this.$http.post('/search', {
            name: this.name,
            company: this.company
        }).then(function (xhr) {
            this.contacts.unshift(xhr.data)
        })

        this.name = ''
        this.company = ''
    },

Upvotes: 1

Related Questions