Charles Julien
Charles Julien

Reputation: 465

Passing data from child to parent to parent in Vue.js with method $emit()

I can't pass data from child to parent routers with vue.js.

From few research, including on stack overflow, it is very clear that we must use the $emit() method from the child. I played around between the documentation, stackoverflow and some youtube tutorials but there is still something I miss and I do wrong.

Below is my router Menubar.vue

<template>
    <div id="app" class="container-fluid">
         <div @clicked="onClickChild">
            <p>login is set to {{ loggedin }}</p>
            <p>Route query login {{ this.$route.query.loggedin }}</p>
        </div>
        <div v-if="!loggedin">
            <nav>
                <!--<router-link class="btn btn-primary" to="/">Customers</router-link>-->
                <router-link class="btn btn-primary" to= "/menubar/login">Login</router-link>
                <router-link class="btn btn-primary" to="/menubar/register">Register</router-link>
            </nav>
        </div>
        <div v-else>
            <nav>
                <!--<router-link class="btn btn-primary" to="/">Customers</router-link>-->
                <button class="btn btn-primary" v-on:click="logout()">Logout</button>
                <router-link class="btn btn-primary" to="/edit">Edit</router-link>
            </nav>
        </div>

        <br/>
        <router-view/>
    </div>
</template>

<script>
    export default {
        name: "menubar",
        data(){
            return{
                loggedin:false,
            }
        },
        created() {
            if(this.$route.query.loggedin){
                this.loggedin = this.$route.query.loggedin;
            }
        },
        methods: {
            logout(){
                this.loggedin = false;
            },
            onClickChild (value) {
                this.loggedin = value;
                console.log(value) // someValue
            }
        }
    }
</script>

And its child Login.vue

<template>
    <div class="submitform">
        <div class="form-group">
            <label for="username">Username</label>
            <input type="text" class="form-control" id="username" required v-model="user.username" name="username">
        </div>

        <div class="form-group">
            <label for="password">Password</label>
            <input type="password" class="form-control" id="password" required v-model="user.password" name="password">
        </div>

        <button v-on:click="logUser()" class="btn btn-success">Connect</button>
</template>

<script>
    import router from '../../router'

    export default {
        name: "login",
        data(){
            return{
                user: {
                    id: 0,
                    username: "",
                    password: ""
                },
            }
        },
        methods:{
            logUser(){
                var loggedin = true;
                this.$emit('clicked', loggedin);
                router.push({ name: "menubar" });
            }
        }
    }
</script>

my router.js

{
        path: "/menubar",
        name: "menubar",
        component: Menubar,
        children: [
            {
                path: "login",
                name: "login",
                component: Login,
            },
            {
                path: "register",
                name: "register",
                component: Register,
            }
        ]
    }

the console.log should print true or false to give track my params 'loggedin' Instead, no idea if this is linked, I have this: [HMR] Waiting for update signal from WDS...

which gives in my mozilla browser (same in Chrome):

The address wasn’t understood Firefox doesn’t know how to open this address, because one of the following > protocols (view-source, webpack) isn’t associated with any program or is not allowed in this context. You might need to install other software to open this address."

Thanks in advance for your help.

Upvotes: 4

Views: 2685

Answers (2)

JeanMi
JeanMi

Reputation: 290

In your case, the component listening to the event is not a component child:

<div @clicked="onClickChild">[...]</div>

Here the child is a div, however, if you want to be able to listen to an emit signal from a child component, the listener should be associated with this specific child component. In this case something like:

<Login @clicked="onClickChild">[...]</Login>

However, if you want to pass data from a child to a parent node in the router you can define a router-view and catch the event like so:

<router-view @clicked="onClickChild" />

Upvotes: 2

Marcelo
Marcelo

Reputation: 2524

From your code, it looks like your child component is emitting the event correctly to the parent. For the error you are receiving in the browser, it's likely to be a typo or a bad URL, as you are doing:

        path: "/menubar",
        name: "menubar",
        component: Menubar,
        children: [
            {
                path: "/menubar/login",

Which will produce a path like /menubar/menubar/login which looks wrong. https://router.vuejs.org/guide/essentials/nested-routes.html

Upvotes: 0

Related Questions