16

This seems like a fairly basic question but I can't seem to find a definitive (or even working) answer.

I have my root instance:

var vm = new Vue({
  el: '#app',

  // Data
  data: {
      events: {}
  },

  // Methods
  methods: {

    fetchEvents: function(){
      this.$http.get('/api/events').success(function(theseEvents) {
      this.$set('events', theseEvents);

      }).error(function(error) {

      });

    }
},

ready: function(){

  this.fetchEvents();

}

});

And I have a separate component in which I want to list out the events that are stored in the root instance. At the moment it looks like this:

var EventsList = Vue.extend({

template: '<ul><li v-for="event in events"><h2>{{ event.title }}</h2><p>{{ event.body }}</p></li></ul>',

data: function(){
  return {
    events: {}
  }
},

methods: {

  syncEvents: function(){
    this.$set('events', this.$parent.events);
  }

},

// When ready...
ready: function(){
  this.syncEvents();
}
}

This doesn't seem to work. I have also tried this.$root.events to no avail. What is the correct way to go about this? Bear in mind I want to reference the data from the root, not create a copy with its own scope.

EDIT: trying to use props, here is the list component, which is also not working:

var EventsList = Vue.extend({

template: '<ul><li v-for="event in events"><h2>{{ event.title }}</h2><p>{{ event.body }}</p></li></ul>',

props: ['events']

}
76484
  • 8,498
  • 3
  • 19
  • 30
Chris
  • 1,557
  • 5
  • 19
  • 36
  • Are you sure you don't want to use two-way sync with props? That way, you wouldn't have to tightly couple the two components. – nils Mar 01 '16 at 13:06
  • Sorry I'm fairly new to this. Can you explain what you mean? I put the events in the root instance as I will want to use them in many components down the line. – Chris Mar 01 '16 at 13:08
  • Will those components change the `events` as well or will it be read-only? I'll explain in a sec. – nils Mar 01 '16 at 13:12
  • They should just be a direct reference, so they can change. – Chris Mar 01 '16 at 13:23

3 Answers3

7

Using props, you can easily pass the same data from parent to children. Since I don't know how you linked the root instance and the EventList together, I'm going to assume you registered it as a global component.

The documentation states:

Note that if the prop being passed down is an Object or an Array, it is passed by reference. Mutating the Object or Array itself inside the child will affect parent state, regardless of the binding type you are using.

So you will be using the same object throughout all your components when you pass it as a prop.

var vm = new Vue({
  el: '#app',

  // Data
  data: {
      events: {}
  },

  // Methods
  methods: {

    fetchEvents: function(){
      this.$http.get('/api/events').success(function(theseEvents) {
      this.$data.events = theseEvents; // You don't need to use $set here

      }).error(function(error) {

      });

    }
},

ready: function(){

  this.fetchEvents();

}

});

EventList:

var EventsList = Vue.extend({

template: '<ul><li v-for="event in events"><h2>{{ event.title }}</h2><p>{{ event.body }}</p></li></ul>',

data: function(){
  return {
  }
},
props: {
    events: Object, // assuming that your prop is an object
},
}

// Register the vue component globally, if you want to:
Vue.component('eventlist', EventsList);

In the root vue instance template, you can pass the root vue instances events as a property called events in the child component:

<div class="app">
    <!-- events is passed using the :events prop -->
    <eventlist :events="events">
    </eventlist>
</div>
nils
  • 25,734
  • 5
  • 70
  • 79
3

That's what "Props" are for:

http://vuejs.org/guide/components.html#Props

If you pass an object/array as a prop (what your events data will surely be), it's two-way syncing automatically - change events in the child, they are changed in the parent.

If you pass simple values (strings, numbers - e.g. only event.name) via props, you have to explicitly use the .sync modifier: http://vuejs.org/guide/components.html#Prop_Binding_Types

James Toomey
  • 5,635
  • 3
  • 37
  • 41
Linus Borg
  • 23,622
  • 7
  • 63
  • 50
  • Ok i've just done a bit of reading on props. Seems I should just have to add props: ['events'] to the eventList component for the template to work? It doesn't work... – Chris Mar 01 '16 at 13:15
  • Make sure you registered your component globally as @nils indicates and also make sure you pass the :events prop to the child where its being declared – Timothy Feb 16 '17 at 12:05
0
this.$root.events

that will reference the root component, "that is the main.js or index.js or app.js" no matter the component you are in, using props requires that you pass it down each component supposing you want to use it in a third child component.

Benjiro
  • 101
  • 2
  • 14