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

Create 'reactive' representation of state of datat in Parse.Object eg for use in libraries like React, VueJS, etc #1316

Closed
tremendus opened this issue Mar 11, 2021 · 3 comments
Labels
type:feature New feature or improvement of existing feature

Comments

@tremendus
Copy link

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Front end libraries like Vue and React are 'reactive' front end libraries that support the automatic update to the UI when underlying data behind the UI changes. (eg. completing a task changes the status icon and label). To work, they require a POJO-like object to bind to. In the case of Vue v2, it creates getters/setters to the object. in Vue 3 it's proxies. I'm not sure about react.

The problem: Parse.Object only exposes a frozen object (object.attributes) or the get() method, neither of which can be bound in Vue (or React, so I gather). This limits the usefulness of Parse in front end frameworks like Vue and React that rely on and offer data binding.

Describe the solution you'd like
A clear and concise description of what you want to happen.
Parse.Object should expose an representation of the current state in the underlying data that can be bound to.
Changes to this representation should flow back to the underlying state

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
As a prototype for a demo/proof of concept I'm working on, I've created a custom class extension to the Parse.Object that essentially proxies the various set methods (set, setACL, etc) to proxy the request to both the Parse.Object and a POJO bound at this._data.

Additional context
Add any other context or screenshots about the feature request here.
I would imagine that with the popularity of React and Vue and friends that adding such a feature would increase the appeal of Parse to these users. It's a big limitation and a bit of a difficult one to overcome - for various reasons - by proxying the set/get methods. A more robust solution could be created if it came from within the Parse internals.

@dplewis
Copy link
Member

dplewis commented Mar 11, 2021

@dblythy I remember you were using .toJSON() for binding and recently did a PR for subclassing to use with Vue. Do you have any ideas to help with this issue / feature?

@dplewis dplewis added enhancement type:feature New feature or improvement of existing feature labels Mar 11, 2021
@dblythy
Copy link
Member

dblythy commented Mar 12, 2021

Hey Diamond,

Previously I was using toJSON to pass all the fields to Vue from the Parse Object, and then using the new dirty method in fromJSON to override it would look something like this:

<input type="text" placeholder="Monster Name" v-model="monster.name"/>
<button @click="saveMonster">Save</button>
...
data() {
  return {
     monster: {};
  }
},
async created() {
  const query = new Parse.Query('Monster');
  const monster = await query.first();
  this.monster = monster.toJSON();
},
methods: {
  async saveMonster() {
     const monster = new Parse.Object.fromJSON(this.monster, false, true);
     await monster.save();
  }
}

Now here, if you could use dot notation on a Parse.Object, you would save a large amount of code.

I've written a little subclass that should give you a rough idea of how the behaviour needs to be for VueJS.

This allows for the following code to get and set the field "name" on the "monster" Parse Object.

<input type="text" placeholder="Monster Name" v-model="monster.name"/>
/* so you could build a whole form input without needing to worry about getting and setting the fields. */
<button @click="monster.save()">Save</button>

I'm not sure if this behaviour should be added to the core JS SDK.

The problem is that it would be convenient to be able to get/set a Parse Objects fields using const field = object.fieldName, or object.fieldName = field.

In my subclass, I override _finishFetch and set the properties directly on the Parse Object. This allows me to set a input, for example, to object.fieldName. If object is updated via LQ for example or a manual fetch, _finishFetch should still be called. I then override .save to properly .set the keys so that the data is updated on the server.

I'm not sure if this approach is the "best" way for the core package, as setting every field will increase the size of a Parse Object in memory.

Other ideas:

  • Return a "Proxy" instead of a Parse Object. This allows you to intercept setting properties with unknown names to the Parse Object. However, this doesn't seem to work with VueJS as Vue uses proxies internally.
  • Allow mutating of .attributes. If attributes are mutated, update the fields and save.

@mtrezza mtrezza removed the type:feature New feature or improvement of existing feature label Oct 5, 2021
@mtrezza mtrezza added type:feature New feature or improvement of existing feature and removed type:improvement labels Dec 6, 2021
@tremendus tremendus closed this as not planned Won't fix, can't repro, duplicate, stale Mar 15, 2023
@dblythy
Copy link
Member

dblythy commented Mar 15, 2023

We are looking at introducing this via #1484

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:feature New feature or improvement of existing feature
Projects
None yet
Development

No branches or pull requests

4 participants