简体   繁体   中英

Using VueFire, how do I order my list by date in descending order (newest to oldest)?

I am currently creating a project using VueJS, Firebase and VueFire. The issue I'm having is ordering a lists of posts newest to oldest.

I've tried to use Firebase's built in queries like list.orderByChild('date') , but no luck.

I know I need to use Array.sort((a,b) => { return new Date(a.date) - new Date(b.date) }) but I'm having a tough time wrapping my head around getting it to work with VueFire, or even creating a Vue filter with it.

Let me know if I can provide anything else.

This is what my Database looks like:

1

Here is my code:

2

Assuming that you are fetching the posts and storing them in an array[ ] and then looping through the array using v-for and displaying the posts.

You can use this workaround:

  • by default when you fetch posts from firebase, you get the posts from oldest to newest

  • so you can use Array.unshift() method to add the posts to your posts array which reverses the order of items getting added to your array

  • since the items are added in reverse order in your array you can now regularly loops through the posts using v-for and display the oosts

The most easy option (besides using orderByChild('date') ) would probably be a computed property , where you would have something like this:

import firebase from './firebase'

var vm = new Vue({
  el: '#example',
  firebase // bring in your firebase module here
  data: {
    message: 'Hello'
  },
  computed: {
    // a computed getter
    sortedList: function () {
      // `this` points to the vm instance
      return this.items.sort((a,b) => { return new Date(a.date) - new Date(b.date) })
    }
  }
})

this property will automatically update when any of the properties it depends on changes thus keeping it al real time & reactive :)

Thanks both of you for responding!

What I actually ended up doing was adding another value to the list item I was saving to the database.

I added the child order so when I saved the object to firebase it looked something like this:

var newItem = {
  title: "Title to the post",
  order: (this.itemListFromDatabase.length + 1) * -1
}
firebase.database().ref('itemList').push(newItem);

I gave it a negative value because when you call orderByChild() it will order it in ascending order. Seems to be working just fine right now.

When I retrieve my list it looks like this:

firebase: {
  list: firebase.database().ref('list').orderByChild('order')
}

According to Vuefire readme :

If you want to have automatic rebind (pretty much like a computed property) use a $watch and call $unbind and then $bindAsArray

Once to firebase variable was assigned a value

firebase: {
  posts: firebase.database().ref('posts')
}

it behaves like const. In order to change its value, you must unbind it first

this.$unbind('posts')

then reassign with reordered posts, for instance.

this.$bindAsArray('posts', postsRef.orderByChild(this.order))

In example below we watch order variable, once it changed, posts being reassigned with reordered response from firebase

import { postsRef } from '@/firebase' // postsRef = firebase.database().ref('posts')
export default {
  data() {
    return {
      order: 'title' // default order
    }
  },
  firebase: function() {
    return {
      posts: postsRef.orderByChild(this.order)
    }
  },
  methods: {
    setOrder(val) {
      this.order = val
    }
  },
  watch: {
    order: function() {
      if (this.$firebaseRefs.posts) {
        this.$unbind('posts')
      }
      this.$bindAsArray('posts', postsRef.orderByChild(this.order))
    }
  }
}

PS I am aware that this question is no longer relevant, but maybe it will be helpful for others. I just stuck with this problem too, and it took a while to understand, how it actually works.

i have a very simple solution you can use sort method base on you date field on your vuex getters or if you use your states directly you can use in computed method of your component, like this:

const getters = {
  getPosts: state => {
    if (!state.posts) return null;
    return state.posts.sort((a, b) => a.date - b.date);
  },
};

or if your data field is a firebase timestamp you can use like this

const getters = {
  getPosts: state => {
    if (!state.posts) return null;
    return state.posts.sort((a, b) => a.date.seconds - b.date.seconds);
  },

it depends to your date format, if you use seconds, minute or something like this, this method will work fine. and i should mention that firebase timestamps use seconds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM