Every service now includes a new FeathersVuexModel Class and new records are instantiated with that class before getting added to the store.

Model attributes

The following attributes are available on each model:

  • servicePath {String} - Model.servicePath is the path passed to create the FeathersClient service.
  • namespace {String} - Model.namespace holds the value that was used to register the module with Vuex. This will match the servicePath unless you've provided a custom namespace in the Service Module options.
  • store {Vuex Store} - Use Model.store to access the Vuex store. example

Model Methods

Model.find(params)

Model classes have a find method, which is a proxy to the find action. 1.7.0+

// In your Vue component
created () {
  const { Todo } = this.$FeathersVuex
  Todo.find({ query: {} }).then(/* ... */)
}

Model.findInStore(params)

Model classes have a findInStore method, which is a proxy to the find getter. 1.7.0+

// In your Vue component
created () {
  const { Todo } = this.$FeathersVuex
  const todos = Todo.findInStore({ query: {} })
}

Model.get(id, params)

Model classes have a get method, which is a proxy to the get action. 1.7.0+Notice that the signature is more Feathers-like, and doesn't require using an array to passing both id and params.

// In your Vue component
created () {
  const { Todo } = this.$FeathersVuex
  Todo.get(this.id).then(/* ... */)
}

Model.getFromStore(id, params)

Model classes have a getFromStore method, which is a proxy to the get getter. 1.7.0+ Notice that the signature is more Feathers-like, and doesn't require using an array to passing both id and params.

// In your Vue component
created () {
  const { Todo } = this.$FeathersVuex
  const todo = Todo.getFromStore(this.id)
}

Creating instances

The FeathersVuex plugin for Vue allow convenient access to all Model constructors. You can create a Model instance by getting a reference to a Model class from the $FeathersVuex object:

// In your Vue component
created () {
  const { Todo } = this.$FeathersVuex
  const todo = new Todo({ description: 'Do something!' })
}

You can also reference this directly from the Vue module:

import Vue from 'vue'

const { Todo } = Vue
const todo = new Todo({ description: 'Do something!' })

The examples above show instantiating a new Model instance without an id field. In this case, the record is not added to the Vuex store. If you instantiate a record with an id field, it will get added to the Vuex store. Note: This field is customizable using the idField option for this service.

Now that we have Model instances, let's take a look at the functionality they provide. Each instance will include the following methods:

  • .save()
  • .create()
  • .patch()
  • .update()
  • .clone()
  • .commit()
  • .reset()

Remember, if a record already has an attribute with any of these method names, it will be overwritten with the method.

These methods give access to many of the store actions and mutations. Using Model instances, you no longer have to use mapActions for create, patch, update, or remove. You also no longer have to use mapMutations for createCopy, commitCopy, or rejectCopy.

store.dispatch('todos/find', { query: {} })
  .then(response => {
    const { data } = response
    const todo = data[0]

    todo.description = 'Read Nuxt.js docs'
    todo.save() // Calls store.dispatch('todos/patch', [item.id, item, {}])
  })

instanceDefaults | Object

Do you find yourself spending time writing defaults into your form components? Maybe you wrote a utility for yourself or found one on npm that can do the trick for you. That's a thing of the past. You can now specify the default values for Model instances by using the instanceDefaults option when using the service plugin. Here's what it looks like:

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: '',
        isComplete: false
      }
    })
  ]
})

With the above configuration, when you create a Todo instance, it will have the attributes provided as instanceDefaults. This is especially useful for binding to form data. If the attributes aren't defined while binding, the automatic Vue reactivity won't work. Remember to not set any of the attributes to undefined, but instead use null. If not, the reactivity breaks, and you might spend some time wondering why your form is broken.

instanceDefaults | Function 1.7.0+ recommended

A much more powerful API is available when you provide instanceDefaults as a function. The function will be called with the following arguments and should return an instanceDefaults object.

  • data {Object} - The instance data
  • An utils object containing these props:
    • store - The vuex store
    • Model {FeathersVuexModel} - The current Model (the same as the current instance's constructor)
    • Models {Object} The globalModels object, which is the same as you'll find inside a component at this.$FeathersVuex.

This API allows for a lot of flexibility. In the below example, each todo instance has a get user property. If the instance has a userId, the correct user record will automatically be fetched from the store.

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 (data, { store, Model, Models }) {
        return {
          description: '',
          isComplete: false,
          userId: null,
          get user () {
            if (this.userId) {
              const user = Models.User.getFromStore(this.userId)

              // Fetch the User record if we don't already have it
              if (!user) {
                Models.User.get(this.userId)
              }

              return user
            } else {
              return null
            }
          }
        }
      }
    })
  ]
})

Instance Methods

instance.save(params)

The save method is a convenience wrapper for the create/patch methods, by default. If the records has no _id, the instance.create() method will be used. The params argument will be used in the Feathers client request. See the Feathers Service docs, for reference on where params are used in each method.

// In your Vue component
created () {
  const { Todo } = this.$FeathersVuex
  const todo = new Todo({ description: 'Do something!' })

  todo.save() // --> Creates the todo on the server.
}

Once the create response returns, the record will have an _id. If you call instance.save() again, it will call instance.patch(). Which method is used depends soletly on the data having an id (that matches the options.idfield for this service).

As mentioned, save performs either create or patch, but you can use the preferUpdate option to change the behavior to create/update.

instance.create(params)

The create method is a shortcut for calling the create action (service method) using the instance data. The params argument will be used in the Feathers client request. See the Feathers Service docs, for reference.

You might not ever need to use .create(), but can instead use the .save() method. Let feathers-vuex call create or patch.

const { Todo } = this.$FeathersVuex
const data = { description: 'Do something!' }
const todo = new Todo(data)

todo.create() // --> Creates the todo on the server using the instance data

instance.patch(params)

The patch method is a shortcut for calling the patch action (service method) using the instance data. The instance's id field is used for the patch id. The params argument will be used in the Feathers client request. See the Feathers Service docs, for reference.

Similar to the .create() method, you might not ever need to use .patch() if you just use .save() and let feathers-vuex figure out how to handle it.

const { Todo } = this.$FeathersVuex
const todo = new Todo({ id: 1, description: 'Do something!' })

todo.description = 'Do something else'

todo.patch() // --> Sends a `patch` request the with the id and description.

Note: Currently, patch sends all data, not just what has changed. In a future update, it will only send the fields that have changed.

instance.update(params)

The update method is a shortcut for calling the update action (service method) using the instance data. The instance's id field is used for the update id. The params argument will be used in the Feathers client request. See the Feathers Service docs, for reference.

Use .update() whenever you want to completely replace the data on the server with the instance data. You can also set the preferUpdate option to true to make .save() call .update() when an id field is present on the instance.

const { Todo } = this.$FeathersVuex
const todo = new Todo({ id: 1, description: 'Do something!' })

todo.description = 'Do something else'

todo.update() // --> Sends a `update` request the with all instance data.

instance.remove(params)

The remove method is a shortcut for calling the remove action (service method) using the instance data. The instance's id field is used for the remove id. The params argument will be used in the Feathers client request. See the Feathers Service docs, for reference.

const { Todo } = this.$FeathersVuex
const todo = new Todo({ id: 1, description: 'Do something!' })

todo.save()
  .then(todo => {
    todo.remove() // --> Deletes the record from the server
  })

instance.clone()

The .clone() method creates a deep copy of the record and stores it on Model.copiesById. This allows you to make changes to the clone and not update visible data until you commit or save the data.

const { Todo } = this.$FeathersVuex
const todo = new Todo({ id: 1, description: 'Do something!' })
const todoCopy = todo.clone()

todoCopy.description = 'Do something else!'
todoCopy.commit() // --> Update the data in the store.

console.log(todo.description) // --> 'Do something else!'
console.log(todoCopy.description) // --> 'Do something else!'

There's another use case for using .clone(). Vuex has a strict mode that's really useful in development. It throws errors if any changes occur in the Vuex store state outside of mutations. Clone really comes in handy here, because you can make changes to the clone without having to write custom Vuex mutations. When you're finished making changes, call .commit() to update the store. This gives you strict mode compliance with little effort!

Finally, if for some reason you prefer to keep the copies in the Vuex store and use custom mutations for all update, you can set the keepCopiesInStore option to true. This will cause the copies to be stored in state.copiesById.

instance.commit()

const { Todo } = this.$FeathersVuex
const todo = new Todo({ id: 1, description: 'Do something!' })
const todoCopy = todo.clone()

todoCopy.description = 'Do something else!'
todoCopy.commit() // --> Update the data in the store.

console.log(todo.description) // --> 'Do something else!'
console.log(todoCopy.description) // --> 'Do something else!'

instance.reset()

const { Todo } = this.$FeathersVuex
const todo = new Todo({ id: 1, description: 'Do something!' })
const todoCopy = todo.clone()

todoCopy.description = 'Do something else!'
todoCopy.reset() // --> Resets the record to match the one in the store.

console.log(todo.description) // --> 'Do something!'
console.log(todoCopy.description) // --> 'Do something!'