4

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?

Aaron N. Brock
  • 4,276
  • 2
  • 25
  • 43
  • This is strange. I've tried to reproduce your case and the resulting `assets` array is an array of objects corresponding to the `data()` method, i.e. without any `.key` property. Are you using a specific setting? – Renaud Tarnec Apr 08 '20 at 11:15
  • @RenaudTarnec It's a read-only property as documented here: https://vuefire.vuejs.org/vuexfire/binding-subscriptions.html#using-the-data-bound-by-vuexfire I just added it to the example to show that it does store the key, just not in the form I'd like. – Aaron N. Brock Apr 08 '20 at 11:43
  • I try to understand how do you get this `[{.key: "id1" /* etc. */ }, ...]` array. Can you please share the code used to get it? – Renaud Tarnec Apr 08 '20 at 12:26
  • @RenaudTarnec I just wrote that part out by hand. But you can get it by just logging a getter which returns `state.assets`. – Aaron N. Brock Apr 08 '20 at 12:41
  • @RenaudTarnec Actually, I did make one typo. It is "id" instead of ".key" by default (I've updated my question) – Aaron N. Brock Apr 08 '20 at 12:42
  • The getter `state.assets` would normally not return the `id` by default, unless this `id` value is included in the document itself. To be able to help you we need to see the code you are using to transform the original array in the one you show in your question. – Renaud Tarnec Apr 08 '20 at 12:48
  • Are you sure about that? I don't believe I'm doing any sort of transformation, and in my console.log in google chrome I'm getting: https://imgur.com/6q392rr – Aaron N. Brock Apr 08 '20 at 12:52
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/211217/discussion-between-renaud-tarnec-and-aaron-n-brock). – Renaud Tarnec Apr 08 '20 at 12:56
  • Did you resolved this issue? I also want to store my collection in vuex in keyed object and not in array. – rendom Jul 09 '20 at 03:28
  • @rendom I did not come to a real solution, but I did open a feature request here: https://github.com/vuejs/vuefire/issues/685 (but it seems you already commented on it) – Aaron N. Brock Jul 10 '20 at 18:51

2 Answers2

4

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>
Community
  • 1
  • 1
Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
0

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

state: {
  assets: {},  // instead of []
},
kraeki
  • 51
  • 1
  • 2