Skip to content

Commit

Permalink
docs: finish updating common patterns page
Browse files Browse the repository at this point in the history
  • Loading branch information
marshallswain committed Oct 21, 2019
1 parent c9f0af1 commit 82ce214
Showing 1 changed file with 50 additions and 122 deletions.
172 changes: 50 additions & 122 deletions docs/common-patterns.md
Expand Up @@ -255,30 +255,33 @@ In summary, you can plan on individual records in the action response data to be

## Basic Data Modeling with `instanceDefaults`

See the [instanceDefaults API](./model-classes.html#instanceDefaults)
See the [instanceDefaults API](./model-classes.html#instancedefaults)

## Model-Specific Computed Properties

You may find yourself in a position where model-specific computed properties would be very useful. [github issue](https://github.com/feathers-plus/feathers-vuex/issues/163) This is already possible using es5 accessors. You can use both getters and setters inside `instanceDefaults`:
You may find yourself in a position where model-specific computed properties would be very useful. [github issue](https://github.com/feathers-plus/feathers-vuex/issues/163). In Feathers-Vuex 1.7, these could be specified in the `instanceDefaults`. As of 2.0, they are specified directly on each Model class:

```js
export default new Vuex.Store({
plugins: [
service('post', {
instanceDefaults: {
description: '',
isComplete: false,
comments: [],
get numberOfCommenters () {
// Put your logic here.
},
set someOtherProp () {
// Setters also work
}
}
})
]
})
class Post extends BaseModel {
// Required for $FeathersVuex plugin to work after production transpile.
static modelName = 'Post'
// Define default properties here
static instanceDefaults() {
return {
description: '',
isComplete: false,
comments: [],
}
}

// Specify computed properties as regular class properties
get numberOfCommenters () {
// Put your logic here.
},
set someOtherProp () {
// Setters also work
}
}
```

## Relationships for Populated Data
Expand Down Expand Up @@ -326,110 +329,41 @@ Suppose a requirement is put on the `/todos` service to populate the `user` in t

Can you see the problem that will occur with this response? When this record is put into the `/todos` store, it will contain a copy of the user record. But we already have the user record in the `/users` store. And what happens when the user data changes? Now it's out of sync. To keep it in sync, you might have to manually listen for `users updated` & `users patched` events. Then you might have to write a custom mutation to update the user record attached to every applicable `todo` record. This gets messy, fast!

There's an easier way to solve this problem. The introduction of `instanceDefaults` allowed for another awesome feature: Model Relationships! To setup a relationship, specify a Model name, as a string, to any property, like this:

```js
instanceDefaults: {
description: '',
complete: false,
userId: null,
user: 'User'
}
```

When this record is instantiated, the `user` attribute will first be turned into a User [model instance](./model-classes.html), stored properly in the `/users` store. The `todo.user` attribute will be a reference to that user. No more duplicate data! Here's an example of how to set this up. The following example specifies that Todo instances can have a `user` attribute that contains a `User` Model instance:

```js
import Vue from 'vue'
import Vuex from 'vuex'
import feathersVuex from 'feathers-vuex'
import feathersClient from './feathers-client'

const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' })

Vue.use(FeathersVuex)
Vue.use(Vuex)

export default new Vuex.Store({
plugins: [
service('todos', {
instanceDefaults: {
description: '',
complete: false,
userId: null,
user: 'User'
}
}),
service('users', {
instanceDefaults: {
email: '',
name: ''
}
})
]
})
```

There's another amazing benefit from these relationships. Because `feathers-vuex` listens to real-time events and keeps data up to date, when the user record changes, the `todo.user` automatically updates!

It's worth noting that this feature also supports arrays. Suppose you had `/users` and `/todos` services, and your `/users` service also returned a `todos` attribute on each record. The setup would look like this:
There's an easier way to solve this problem. Use the new [`setupInstance` method on Model classes](/model-classes.html#setupinstance).

```js
import Vue from 'vue'
import Vuex from 'vuex'
import feathersVuex from 'feathers-vuex'
import feathersClient from './feathers-client'
import feathersClient, { makeServicePlugin, BaseModel } from '../feathers-client'

const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' })

Vue.use(FeathersVuex)
Vue.use(Vuex)
class Todo extends BaseModel {
// Required for $FeathersVuex plugin to work after production transpile.
static modelName = 'Todo'
// Define default properties here
static instanceDefaults() {
return {
email: '',
password: ''
}
}
// Updates `data.user` to be an instance of the `User` class.
static setupInstance(data, { models }) {
if (data.user) {
data.user = new models.api.User(data.user)
}
return data
}
}

export default new Vuex.Store({
plugins: [
service('todos', {
instanceDefaults: {
description: '',
isComplete: false
}
}),
service('users', {
instanceDefaults: {
email: '',
name: '',
todos: 'Todo'
}
})
]
const servicePath = 'todos'
const servicePlugin = makeServicePlugin({
Model: Todo,
service: feathersClient.service(servicePath),
servicePath
})
```

With the `instanceDefaults` shown above, any `todos` returned on the `users` service would be stored in the `/todos` service store and would always be Todo instances.

## Reactive User Data in Auth Store

The `user` record in the auth store is now fully reactive and will automatically update with real-time events. In fact, the record in the auth store is the record in the users store. Please note that if you configure the `userService` option on the `auth` plugin, you must also use the `service` plugin for the `/users` service. The paths must match:

```js
import Vue from 'vue'
import Vuex from 'vuex'
import feathersVuex from 'feathers-vuex'
import feathersClient from './feathers-client'

const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' })

Vue.use(FeathersVuex)
Vue.use(Vuex)
When this record is instantiated, the `user` attribute will first be turned into a User [model instance](./model-classes.html), stored properly in the `/users` store. The `todo.user` attribute will be a reference to that user. No more duplicate data! Here's an example of how to set this up.

export default new Vuex.Store({
plugins: [
service('users'),
auth({
userService: 'users'
})
]
})
```
There's another amazing benefit from these relationships. Because `feathers-vuex` listens to real-time events and keeps data up to date, when the user record changes, the `todo.user` automatically updates!

## Form Binding

Expand Down Expand Up @@ -549,10 +483,4 @@ export default new Vuex.Store({

## Enable Debug Logging

If items aren't not getting added to the store properly, try setting the `debug` option on the service. It enables some additional logging that may be useful for troubleshooting:

```js
service('todos', {
debug: true
})
```
If items aren't not getting added to the store properly, try setting the `debug` option on the `makeServicePlugin` to `true`. It enables some additional logging that may be useful for troubleshooting.

0 comments on commit 82ce214

Please sign in to comment.