Forked from calebroseland/vue-js-data-reactivity.js
Last active
January 5, 2019 21:01
-
-
Save mikeu/441fbae43f2ec629f13ff2d5abde68f5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue' | |
import {DataStore, Record} from 'js-data' | |
// Define a base class that enables property-level vue reactivity and, optionally does so at the relationship-level. | |
export class VueReactiveRecord extends Record { | |
constructor (...args) { | |
// Among other things, this will apply js-data schema if configured to do so; be sure to do `track: true`. | |
super(...args); | |
// Apply vue reactivity. | |
for (let key in this) { | |
Vue.util.defineReactive(this, key, this[key]); | |
} | |
// Add Vue reactivity to relationships as well, when their definitions say to. | |
const relationsByType = this._mapper().relations; | |
// e.g. relationsByType = { hasMany: {...}, belongsTo: {...} } | |
for (const relType in relationsByType) { | |
const relations = relationsByType[relType]; | |
// e.g. relations is all hasMany relationships, or all belongsTo ones. | |
for (const relName in relations) { | |
const relation = relations[relName]; | |
// Now relation is the actual definition of a single relationship on the mapper. | |
// If it has not been explicitly marked for Vue reactivity, move to the next. | |
if (!relation.vueReactive) { continue; } | |
const key = relation.localField; | |
Vue.util.defineReactive(this, key, this[key]); | |
} | |
} | |
// Re-apply the js-data schema. | |
this._mapper().schema.apply(this) ; | |
} | |
}; | |
// Create related record classes that inherit this. | |
export class User extends VueReactiveRecord {}; | |
export class Post extends VueReactiveRecord {}; | |
// Create a store to which we'll add some mappers based on these classes. | |
export const store = new DataStore(); | |
export const userMapper = store.defineMapper('user', { | |
idAttribute: 'id', | |
endpoint: 'users', | |
recordClass: User, | |
schema: { | |
track: true, | |
properties: { | |
id: { type: 'number' /* , or maybe... type: 'string', format: 'uuid' */ }, | |
name: { type: 'string' }, | |
}, | |
}, | |
relations: { | |
hasMany: { | |
post: { | |
localKeys: 'postIds', | |
localField: 'posts', | |
vueReactive: true, | |
}, | |
}, | |
}, | |
}); | |
export const postMapper = store.defineMapper('post', { | |
idAttribute: 'id', | |
endpoint: 'posts', | |
recordClass: Post, | |
schema: { | |
track: true, | |
properties: { | |
id: { type: 'number' /* , or maybe... type: 'string', format: 'uuid' */ }, | |
title: { type: 'string' }, | |
}, | |
}, | |
relations: { | |
belongsTo: { | |
user: { | |
localKeys: 'userId', | |
localField: 'user', | |
}, | |
}, | |
}, | |
}); | |
// Now the properties of users and posts will be reactive in Vue, as will the set of posts | |
// associated with each user. | |
// For a detailed explaination about the properties, see here: https://medium.com/p/525ffe12ad81#c925 | |
// A discussion of the addition of the relationship reactivity is here: | |
// https://www.munderwood.ca/index.php/2018/05/16/adding-vue-reactivity-to-js-data-relationships/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment