0

I have the following setup

Component.vue (display db collections as grid in main page)

...
      <v-flex v-for="i in items" :key="i.id" xs6 sm3 md3>
        <v-card color="primary">
          <v-card-text>
            <h2 
              class="font-weight-regular mb-4"
            >
              {{ i.description }}
            </h2>
          </v-card-text>
        </v-card>
      </v-flex>
...

<script>
import { db } from '~/plugins/firebase.js'

export default {
  data: () => ({
    items: []
  }),
  props: ['reload'],
  watch: {
    reload: function (newVal, oldVal) {
      this.items = items
      alert('changed reload')
    }
  },
  methods: {
    firestore() {
      db.collection('items')
        .get()
        .then(querySnapshot => {
          const items = []
          querySnapshot.forEach(function(doc) {
            const item = doc.data()
            item.id = doc.id
            items.push(useritem)
          })

          this.items = items
        })
        .catch(function(error) {
          alert('Error getting documents: ' + error)
        })
    }
  }
}
</script>

index.vue (main page that has grid component and button to add new collection)

....
    <v-layout mb-4>
      <v-btn 
        @click="submit"
      >
        Add Item
      </v-btn>
    </v-layout>
    <v-layout mb-4>
      <component :reload="reload" />
    </v-layout>
....

<script>
import { db } from '~/plugins/firebase.js'
import component from '~/components/Component.vue'
import moment from 'moment'

export default {
  components: {
    component
  },
  data() {
    return {
      description: 'test',
      date: moment(),
      reload: false
    }
  },
  methods: {
    submit() {
      db.collection('items')
        .add({
          description: this.description,
          deadline: new Date(moment(this.date)),
          status: true
        })
        .then(docRef => {
          this.reload = true
        })
        .catch(error => {
          alert('Error adding document: ', error)
        })
    }
  }
}
</script>

As can be seen, I've added a prop to the component to sort of trigger a reload of data from database whenever a new item is added on the main page using the button.

On successful insert the value changes from false to true. However the component grid does not reload. Refreshing the page shows the new item in grid.

How can i make the component reactive or trigger reload on addition of new item?

Jay
  • 1,392
  • 7
  • 17
  • 44
  • I expected you call the function `firestore()` in the `watch` for `reload`. – vahdet Feb 26 '19 at 11:27
  • @vahdet thanks, i've already tried that to no avail. In any case i should atleast see the alert in the watch get triggered. That does not happen either – Jay Feb 26 '19 at 11:31
  • Your statement *On successful insert the value changes from false to true* made me think that the alert was triggered successfully, but if you say so; try [this solution](https://stackoverflow.com/a/51176290/4636715) featuring `immediate` first and you can inform if the alert fires at least. – vahdet Feb 26 '19 at 11:41
  • I decided to give this solution a try - https://stackoverflow.com/a/37521683/732923. Calling the firestore method from the parent itself using refs. It actually does the job, although it does seem like using refs is a questionable way. – Jay Feb 26 '19 at 11:56

1 Answers1

1

In your firestore method in Component.vue, you are using the get method which according to the firestore documentation, only retrieves the data once, it doesn't listen to any change, you'd have to refresh your page to see your updated changes.

However, to listen to changes to your firestore DB and update accordingly on your website, you have to set a listener, Cloud Firestore sends your listener an initial snapshot of the data, and then another snapshot each time the document changes.

methods: {
    firestore() {
      db.collection("items").onSnapshot(
        snapshot => {
          const documents = snapshot.docs.map(doc => {
            const item = doc.data();
            item.id = doc.id;
            return item;
          });
          this.items = documents;
        },
        error => {
          // handle errors
          alert("Error getting documents: " + error);
        }
      );
  }
Peoray
  • 1,705
  • 2
  • 12
  • 21