1

In resources/assets/js/app.js I have created eventHub Vue instance:

require('./bootstrap');    

var eventHub = new Vue();

Vue.component('todos-list', require('./components/todos/TodoList.vue'));
Vue.component('todos-add', require('./components/todos/TodoAdd.vue'));

const app = new Vue({
    el: '#app'
});

How can I use it in components that are created in separate .vue files?

For example, I also have two components:

  • todos-list located in /components/todos/TodoList.vue, which is used to fetch the data from server-side using vue-resource:

    <template id="todos-list-template">
    <div>
        <ul v-if="todos.length > 0">
            <li v-for="todo in todos">
                {{ todo.title }}
            </li>
        </ul>
    
        <p v-else>You don't hanve any Todos.</p>
    </div>
    </template>
    
    <script>
    export default {
        template: '#todos-list-template',
        data() {
            return {
                todos: {}
            }
        },
    
        mounted() {
            this.$http.get('api/vue/todos').then(function(response) {
                this.todos = response.data;
            });
        },
    
        methods: {
            handleAddedTodo: function(new_todo) {
                this.todos.push(new_todo);
            }
        },
    
        created: function() {
            eventHub.$on('add', this.handleAddedTodo);
        },
    
        destroyed: function() {
            eventHub.$off('add', this.handleAddedTodo);
        }
    }
    </script>
    
  • todos-add located in /components/todos/TodoAdd.vue which is used to add (save) the new 'todo' using vue-resource:

    <template id="todos-add-template">
    <div>
        <form v-on:submit.prevent="addNewTodo()">
            <div class="form-group">
                <input v-model="newTodo.title" class="form-control" placeholder="Add a new Todo">
            </div>
    
            <div class="form-group">
                <button>Add Todo</button>
            </div>
        </form>
    </div>
    </template>
    
    
    <script>
    
    export default {
        template: '#todos-add-template',
        data() {
            return {
                newTodo: { id: null, title: this.title, completed: false }
            }
        },
    
        methods: {
            addNewTodo() {
                this.$http.post('api/vue/todos', { title: this.newTodo.title }).then(function(response) {
                    if (response.status == 201) {
                        eventHub.$emit('add', response.data);
                        this.newTodo = { id: null, title: this.title, completed: false }
                    }
                }, function(response) {
                    console.log(response.status + ' - '+ response.statusText);
                })
            }
        }
    }
    </script>
    

When I add (save) new 'todo' using the todos-add component (TodoAdd.vue) - I want to update data in todos-list component. If I understood well the documentation - for component communication we need to use centralized event hub. And that's what I tried - but I am getting the following error:

eventHub is not defined

I guess because it is defined in app.js, but how can I use in components that are created in separate .vue files?

PeraMika
  • 3,539
  • 9
  • 38
  • 63

2 Answers2

1

You are getting this error because eventHub is actually not defined where you are using it. You have to export this from app.js and import in TodoAdd.vue.

in app.js:

var eventHub = new Vue()
exports.eventHub = eventHub

Add this code in TodoAdd.vue:

<script>
import eventHub from '/path/of/app'
export default {
    template: '#todos-list-template',

This should make eventHub availble in TodoAdd.vue.


Edited

As the comment suggests, you may consider using vuex, as you have data whcih is being used across components, and going forward I see chances of getting it more complex, more event handlers and event listerners, which can quickly become a nightmare to manage.

Saurabh
  • 71,488
  • 40
  • 181
  • 244
  • You may want to look at a tutorial for vuex though for managing state. – John Corry Nov 28 '16 at 02:55
  • @saurabh **1.** Can you explain what `exports.eventHub = eventHub` means, what do you do with that? **2.** My second question is about importing: Since in **app.js** we already require all of these components, can importing of app.js cause some problems since we use Laravel Elixir (Gulp/Webpack) to compile all of these into one file? (in app.js we require these components, and in components we import app.js) – PeraMika Nov 28 '16 at 13:37
  • @PeraMika http://stackoverflow.com/questions/3922994/share-variables-between-files-in-node-js – Saurabh Nov 29 '16 at 11:36
0
var eventHub = new Vue()

You are getting this error because eventHub is actually not defined where you are using it. You have to export this from app.js file. Use this one

window.eventHub = new Vue()
Kerim Kuşcu
  • 417
  • 4
  • 12