[Vuejs]-Send data from one component to another in vue

0đź‘Ť

Sync the property between the 2:

<add-entry :entries.sync="entries"/>

Add it as a prop to the add-entry component:

props: ['entries']

Then do a shallow merge of the 2 and emit it back to the parent:

this.$emit('entries:update', [].concat(this.entries, this.newEntries))

0đź‘Ť

(This was a comment but became to big :D)

Is there a way to pass in the key of name? The entry gets added but doesn’t display because im looping and outputting {{ entry.name }}

That’s happening probably because when you pass “complex objects” through parameters, the embed objects/collections are being seen as observable objects, even if you sync the properties, when the component is mounted, only loads first level data, in your case, the objects inside the array, this is performance friendly but sometimes a bit annoying, you have two options, the first one is to declare a computed property which returns the property passed from the parent controller, or secondly (dirty and ugly but works) is to JSON.stringify the collection passed and then JSON.parse to convert it back to an object without the observable properties.

Hope this helps you in any way.

Cheers.

0đź‘Ť

So with help from @Ohgodwhy I managed to get it working. I’m not sure if it’s the right way but it does seem to work without errors. Please add a better solution if there is one and I’ll mark that as the answer.

I follow what Ohmygod said but the this.$emit('entries:update', [].concat(this.entries, this.newEntries)) didn’t work. Well I never even need to add it.

This is my add-entry.vue component

<template>
    <div 
        class="add-entry"
        v-bind:class="{ 'add-entry--open': addEntryIsOpen }">

        <input
            class="add-entry__input"
            type="text"
            name="addEntry"
            placeholder="Add Entry"
            @keyup.enter="addEntries" 
            v-model="newEntries"
        />

        <button 
            class="add-entry__btn"
            @click="addEntries">Add</button>

    </div>
</template>

<script>

export default {
    name: 'add-entry',
    props: ['entries'],
    data: function() {
        return {
            addEntryIsOpen: false,
            newEntries: ''
        }
    },
    methods: {
        addEntries: function() {
            this.entries.push({name:this.newEntries});
            this.newEntries = '';
        }
    }
}

</script>

And my list-entries.vue component

<template>
    <div class="container-flex">
        <div class="wrapper">

            <div class="entries">

                <div class="entries__header">

                    <div class="entries__header__title">
                        <p>Competition Entries</p>
                    </div>

                    <div class="entries__header__search">
                        <input 
                            type="text" 
                            name="Search" 
                            class="input input--search" 
                            placeholder="Search..." 
                            v-model="search">
                    </div>
                </div>

                <div class="entries__content">
                    <ul class="entries__content__list">
                        <li v-for="entry in filteredEntries">
                            {{ entry.name }} 
                        </li>
                    </ul>
                </div>

                <add-entry :entries.sync="entries"/>

            </div>

        </div>
    </div>
</template>

<script>

import addEntry from '@/components/add-entry.vue'
import pickWinner from '@/components/pick-winner.vue'

export default {
    name: 'entry-list',
    components: {
        addEntry,
        pickWinner
    },
    data: function() {
        return {
            search: '',
            entries: [
                {
                    name: 'Geoff'
                },
                {
                    name: 'Stu'
                },
                {
                    name: 'Craig'
                },
                {
                    name: 'Mark'
                },
                {
                    name: 'Zoe'
                }
            ]
        }
    },
    computed: {
        filteredEntries() {
            if(this.search === '') return this.entries
            return this.entries.filter(entry => {
                return entry.name.toLowerCase().includes(this.search.toLowerCase())
            })   
        }
    }
}

</script>

Leave a comment