Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
anachirino opened this issue Apr 21, 2018 · 13 comments
Open

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

anachirino opened this issue Apr 21, 2018 · 13 comments

Comments

@anachirino
Copy link

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()
}
@posva
Copy link
Member

posva commented Apr 21, 2018

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

@anachirino
Copy link
Author

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

@posva
Copy link
Member

posva commented Apr 21, 2018

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
Copy link
Author

anachirino commented Apr 21, 2018

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

Help your concerns?

@anachirino
Copy link
Author

@posva any updates?

@posva
Copy link
Member

posva commented Apr 29, 2018

not yet, I'll look into this later

@trickstival
Copy link
Collaborator

trickstival commented Oct 7, 2018

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 mentioned this issue Dec 6, 2018
36 tasks
@posva
Copy link
Member

posva commented Jul 16, 2019

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

@chrisspiegl
Copy link

chrisspiegl commented Dec 31, 2022

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 🙈.

Copy link
Member

posva commented Dec 31, 2022

Use Object.defineProperty to make it non enumerable 😉

@BenJackGill
Copy link

BenJackGill commented Mar 29, 2023

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
Copy link

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.

@tlserver
Copy link
Contributor

tlserver commented Dec 4, 2023

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

For who is looking for the serialize option document, it is moved to here now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants