Vuexfire bind Firestore collection to Object instead of a List

1.4k Views Asked by At

I have the following collection in my Firestore database:

scheme

Which I can bind to my vuex store with the following:

state: {
  assets: [],
},

actions: {
  bindAssets: firestoreAction(({ bindFirestoreRef }) => {
    return bindFirestoreRef('assets', db.collection('assets'))
  }),
},

However this binds them to assets as a list, I.e.

[
  {id: "id1" /* etc. */ },
  {id: "id2" /* etc. */ },
  {id: "id3" /* etc. */ },
]

Where as, I'd like it to be bound as:

{
  "id1": { /* etc. */ },
  "id2": { /* etc. */ },
  "id3": { /* etc. */ },
}

How can I achieve this?

2

There are 2 best solutions below

0
On

If you want to transform the assets array (obtained by binding the assets collection) in an Object as shown below

{
  "id1": { /* etc. */ },
  "id2": { /* etc. */ },
  "id3": { /* etc. */ },
}

the following Vuex getter should do the trick:

state: {
  assets: [],
},

actions: {
  bindAssets: firestoreAction(({ bindFirestoreRef }) => {
    return bindFirestoreRef('assets', db.collection('assets'))
  }),
},

getters: {
     assetsObj: state => {

         const arrayToObject = (array) =>
            array.reduce((obj, item) => {
                 obj[item.id] = item
                 return obj
            }, {})

        return arrayToObject(state.assets)

    }
}

Update following your comments (in the chat):

If you want to bind to only one document, you should do as follows, with bindAssetDoc and assetDoc.

STORE

state: {
    assets: [],
    assetDoc: null
},

mutations: vuexfireMutations,

actions: {
    bindAssetDoc: firestoreAction(({ bindFirestoreRef }, payload) => {
        return bindFirestoreRef('assetDoc', db.collection('assets').doc(payload.id))
    }),
    bindAssets: firestoreAction(({ bindFirestoreRef }) => {
        return bindFirestoreRef('assets', db.collection('assets'))
    })
}

COMPONENT opened through /asset/:assetId

<script>
//...
export default {
  created() {
    console.log('OK1');
    this.$store
      .dispatch('bindAssetDoc', { id: this.$route.params.assetId });
  }
};
</script>
0
On

According to the offical documentation of vuexfire you need to initialize your state with {} instead of []

state: {
  assets: {},  // instead of []
},