1

Currently trying to wrap my head around Vue and templates.

I read that you pass data from child -> parent with $emit()

app.js

Vue.component('tweet-postbox', require('./components/tweetPostBox.vue').default);

const app = new Vue({
    el: '#app',
    methods: {
        addTweet (tweet) {
            //from the tweetPostBox.vue postTweet method
            console.log(tweet) 
        }
    }
});

tweetPostBox.vue

<template>
    <div class="post-box">
        <div class="w-100 d-flex align-items-center">
            <div class="profile-image rounded-circle"></div>
            <input v-model="message" type="text" id="tweetText" placeholder="Whats happening?">
        </div>
        <div class="controls d-flex align-items-center w-100">
            <button class="btn btn-primary ml-auto" @click="postTweet" id="postTweet">Tweet</button>
        </div>
    </div>
</template>

<script>
    export default {
        data: function () {
            return {
                message: ''
            }
        },
        methods: {
            postTweet:  async function(){
            let response = await axios.post('/post', {
                message: this.message
            })
            //How to get this response data to the main vue instance?
            this.$emit('addTweet', response);
            }
        }
    }
</script>

I'm trying to get the value into my app.js from the component file... but nothing is console logged. Where am I going wrong?

Update: Added HTML

<div class="container" id="app">
    <tweet-postbox></tweet-postbox>
</div>
ProEvilz
  • 5,310
  • 9
  • 44
  • 74
  • How are you creating the `tweet-postbox` component? Using a template inside the element with id `app`, perhaps? You need to register the listener there. You'd need to use `v-on`, or the shorthand `@`, to listen for the event. – skirtle Jul 21 '19 at 03:15
  • @skirtle I updated my question to show the HTML – ProEvilz Jul 21 '19 at 03:18

3 Answers3

0

Found this great answer on another post: https://stackoverflow.com/a/47004242/2387934

Component 1:

<!-- language: lang-js -->

    this.$root.$emit('eventing', data);

Component 2:
<!-- language: lang-js -->

    mounted() {
        this.$root.$on('eventing', data => {
            console.log(data);
        });
    }
ProEvilz
  • 5,310
  • 9
  • 44
  • 74
  • I would not go anywhere near this code if I were you. It is not demonstrating simple parent/child eventing, it's a much more advanced technique for using `$root` in place of an event bus. You need to learn the basics from the official documentation first, [here](https://vuejs.org/v2/guide/events.html) and [here](https://vuejs.org/v2/guide/components-custom-events.html). – skirtle Jul 21 '19 at 03:30
  • Well, is there an actual downside to using this? – ProEvilz Jul 21 '19 at 03:44
0

You should just need to change the template to:

<div class="container" id="app">
    <tweet-postbox @add-tweet="addTweet"></tweet-postbox>
</div>

The @add-tweet part registers an event listener for the add-tweet event. I've used kebab case to avoid browser case-sensitivity problems. You'd need to emit the event with the same name, this.$emit('add-tweet', response). See the offical documentation to confirm that kebab case is the way to go.

The ="addTweet" parts assigns the method addTweet as the listener.

https://v2.vuejs.org/v2/guide/events.html#Method-Event-Handlers

tony19
  • 125,647
  • 18
  • 229
  • 307
skirtle
  • 27,868
  • 4
  • 42
  • 57
-1

First of all, please fix your coding style, there's a lot of issues including indentation errors, try using eslint maybe.

Second, let's break this.$emit('addTweet') down a bit:

  • this is in that line refers to the instance of the Vue component, thus an instance of TweetPostBox.
  • When you call $emit with a addTweet, you're dispatching an event within the component.

Now that addTweet is dispatched, what's going to happen next? Vue is going to find all event handlers that handle addTweet and executes them.

Now in your case, you do not have any event handlers for this event. addTweet in your parent component is simply a local function in that component, it is not an event listener by any means.

To register an event listener, Vue provides @ syntax, and you're already using that with @click, so just like you are doing @click="dosomething" (thus registering an event handler for onClick you need to use @add-tweet. (@addTweet also works but it is against coding style standards, Vue automatically handles the conversion for you)

OverCoder
  • 1,472
  • 23
  • 33