Skip to content

Make it easy to access the per item firebase refs. #180

Open
@anachirino

Description

@anachirino

If you add res['.ref'] = _getRef(snapshot) to the createRecord function. Like:

function createRecord (snapshot) {
  var value = snapshot.val()
  var res = isObject(value)
    ? value
    : { '.value': value }
	res['.key'] = _getKey(snapshot)
	res['.ref'] = _getRef(snapshot);
  return res
}

Then we can more easily access the firebase reference that is associated with a given item. The example in the readme could be changed from:

deleteItem: function (item) {
   this.$firebaseRefs.items.child(item['.key']).remove()
}

to:

deleteItem: function (item) {
   item['.ref'].remove()
}

Activity

posva

posva commented on Apr 21, 2018

@posva
Member

mmh, this is interesting. Any situation when $firebaseRefs is not enough?

anachirino

anachirino commented on Apr 21, 2018

@anachirino
Author

It's just easier access. Make the resulting user code much more readable IMHO.

posva

posva commented on Apr 21, 2018

@posva
Member

oh wait, you're asking to add a ref for every single element? That is too much. I will have to think about it. I like how practical it is but it introduces other problems

anachirino

anachirino commented on Apr 21, 2018

@anachirino
Author

would making it a function like: res['.ref'] = function() { return _getRef(snapshot); }

Help your concerns?

anachirino

anachirino commented on Apr 28, 2018

@anachirino
Author

@posva any updates?

posva

posva commented on Apr 29, 2018

@posva
Member

not yet, I'll look into this later

trickstival

trickstival commented on Oct 7, 2018

@trickstival
Collaborator

would making it a function like: res['.ref'] = function() { return _getRef(snapshot); }

Help your concerns?

@anachirino or it could be a getter with Object.defineProperty

function createRecord (snapshot) {
  var value = snapshot.val()
  var res
  if (isObject(value)) {
    res = value
  } else {
    res = {}
    Object.defineProperty(res, '.value', {
      value: value
    })
  }
  Object.defineProperty(res, '.key', {
    value: _getKey(snapshot)
  })
  Object.defineProperty(res, '.ref', {
    get: function () {
      return _getRef(snapshot)
    }
  })
  return res
}
posva

posva commented on Jul 16, 2019

@posva
Member

For the moment, this is now achievable with the serialize option (https://vuefire.vuejs.org/api/vuefire.html#options-serialize)

chrisspiegl

chrisspiegl commented on Dec 31, 2022

@chrisspiegl

I was able to achieve the result by doing this in my main.js:

import { VueFire, VueFireAuth, globalFirestoreOptions, firestoreDefaultConverter } from 'vuefire'

globalFirestoreOptions.converter = {
  // the default converter just returns the data: (data) => data
  toFirestore: firestoreDefaultConverter.toFirestore,
  fromFirestore: (snapshot, options) => {
    const data = firestoreDefaultConverter.fromFirestore(snapshot, options)
    // if the document doesn't exist, return null
    if (!data) return null
    // add anything custom to the returned object
    // data.metadata = snapshot.metadata
    data.ref = snapshot.ref
    return data
  },
}

note the line: data.ref = snapshot.ref

Sadly, it does not do the same for the referenced children which are loaded. Those end up not having a ref.

UPDATE: I later noticed that this also get's pushed to the firestore upon update. So it's not read only and I don't know how I would make it read only 🙈.

posva

posva commented on Dec 31, 2022

@posva
Member

Use Object.defineProperty to make it non enumerable 😉

BenJackGill

BenJackGill commented on Mar 29, 2023

@BenJackGill

How does this work with TypeScript?

I have tried this without any luck.

globalFirestoreOptions.converter = {
  // the default converter just returns the data: (data) => data
  toFirestore: firestoreDefaultConverter.toFirestore,
  fromFirestore: (snapshot, options) => {
    const data = firestoreDefaultConverter.fromFirestore(snapshot, options);
    // if the document doesn't exist, return null
    if (!data) return null;
    // add anything custom to the returned object
    // Adding a ref (aka DocumentReference)
    Object.defineProperty(data, "ref", {
      value: snapshot.ref,
      enumerable: false,
      writable: true,
      configurable: true,
    });
    return data as DocumentData & {
      readonly id: string;
      readonly ref: DocumentReference<DocumentData>;
    };
  },
};

The code works, because I can access ref on my useDocument objects. But TypeScript still complains with an error.

For example, when I try to access ref on a User document I get this TypeScript error: Property 'ref' does not exist on type 'User & { readonly id: string; }'. ts(2339)

BenJackGill

BenJackGill commented on Mar 30, 2023

@BenJackGill

Also I have noticed this does not work for useCollection(). It only works for useDocument().

When using useCollection() it would be good to have a collection reference on the collection itself, and a document reference stored on a ref property of on each document in the collection array.

2 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @posva@chrisspiegl@anachirino@BenJackGill@tlserver

        Issue actions

          Make it easy to access the per item firebase refs. · Issue #180 · vuejs/vuefire