Configuration
Creating a Base Model
See the API reference for a list of available options.
The first step is to create a base model to define the default options, in order to abstract configuration from your models. It should extend the Base Model of vue-api-query.
The base model must implement two methods:
baseURL
- The base url of your REST API.request
- The default request method.
Let's create a new file Model.js
in models
directory:
import { Model as BaseModel } from 'vue-api-query'
export default class Model extends BaseModel {
// Define a base url for a REST API
baseURL() {
return 'http://my-api.com'
}
// Implement a default request method
request(config) {
return this.$http.request(config)
}
}
$http
property is the HTTP Client Instance configured in
Installation
section.
Creating the Domain Models
Now let's create our domain models that extends the base model. We can create as many models as we like.
Each model must implement:
resource
- The resource route of the model.
We can create a User model like this:
import Model from './Model'
export default class User extends Model {
// Set the resource route of the model
resource() {
return 'users'
}
}
This User model will make request to /users
route as defined in resource
.
We can also add extra methods and computed properties:
import Model from './Model'
export default class User extends Model {
// Set the resource route of the model
resource() {
return 'users'
}
// Computed properties are reactive -> user.fullName
// Make sure to use "get" prefix
get fullName () {
return `${this.firstname} ${this.lastname}`
}
// Method -> user.makeBirthday()
makeBirthday() {
return this.age += 1
}
}
Typescript
If we are working on a Typescript project, we can infer the types of the fields, so we have intellisense.
Directly in Model
import Model from './Model'
export default class User extends Model {
firstName: string
lastName: string
age: number
...
}
Using an Interface
import Model from './Model'
interface User {
firstName: string
lastName: string
age: number
}
class User extends Model {
...
}
export default User
!
operator to make non-null assertion.
Changing the Primary Key
primaryKey
is set to
id
.
See the API reference
It's possible to change the primary key of a model by implementing the primaryKey
method.
This way, the specified key will be used to build the query.
Let's create a Post model and set its primary key to slug
.
import Model from './Model'
export default class Post extends Model {
// Set the resource route of the model
resource() {
return 'posts'
}
// Define the primary key of the model
primaryKey() {
return 'slug'
}
This Post model will build the query using the slug
as primary key: /posts/{slug}
Defining Relationships
It's also possible to define the relationships of our models. By doing this, model instances will be automatically applied to relationships, giving you access to all of their features.
Eager Loaded Relationships
See the API reference
For relationships that have been eager loaded, we only need to implement the relations
method
to apply their model instances. It works for collections too.
The relations
method must return an object, which the key is the property of the relationship, and the value is the
model instance.
Let's set up an eager loaded User, and an eager loaded collection of Comments for our Post model:
import Model from './Model'
import User from './User'
import Comment from './Comment'
export default class Post extends Model {
// Set the resource route of the model
resource() {
return 'posts'
}
// Define the primary key of the model
primaryKey() {
return 'slug'
}
// Apply model instances to eager loaded relationships
relations() {
return {
user: User,
comments: Comment
}
}
Now we can easily access an instance of the User model containing the eager loaded data
using the specified key: post.user
The relations
method also support nested keys, by dot notation:
import Model from './Model'
import User from './User'
import Comment from './Comment'
export default class Post extends Model {
// Set the resource route of the model
resource() {
return 'posts'
}
// Define the primary key of the model
primaryKey() {
return 'slug'
}
// Apply model instances to eager loaded relationships
relations() {
return {
'relationships.user': User,
'relationships.comments': Comment
}
}
Then we can access using the specified key: post.relationships.user
Lazy Loading Relationships
See the API reference
To lazy load relationships, we just need to set up custom methods. Each method must return hasMany(ModelInstance)
.
Let's set up a method to lazy load Posts in our User model:
import Model from './Model'
import Post from './Post'
export default class User extends Model {
// Set the resource route of the model
resource() {
return 'users'
}
// Lazy load the posts that belongs to the user
posts() {
return this.hasMany(Post)
}
// Computed properties are reactive -> user.fullName
// Make sure to use "get" prefix
get fullName () {
return `${this.firstname} ${this.lastname}`
}
// Method -> user.makeBirthday()
makeBirthday() {
return this.age += 1
}
}
Then we simply call the method user.posts()
to lazy load the posts that belongs to the user.
Customizing Query Parameters
See the API reference
If needed, we can easily customize the name of the query parameters by overriding the parameterNames
method.
We can globally customize the names by doing this in the Base Model:
import { Model as BaseModel } from 'vue-api-query'
export default class Model extends BaseModel {
// Define a base url for a REST API
baseURL() {
return 'http://my-api.com'
}
// Implement a default request method
request(config) {
return this.$http.request(config)
}
// Override default query parameter names
parameterNames() {
const defaultParams = super.parameterNames()
const customParams = {
include: 'include_custom'
}
return { ...defaultParams, ...customParams }
}
}
Configuring Query Parameters Parser
See the API reference and qs
We may also need to configure the parser to match our needs. By default, it is configured to match
spatie/laravel-query-builder
, which uses comma
array format.
If we want, for example, to change this behaviour to indices
, we can configure the stringify options of qs
by overriding the stringifyOptions
method.
We can globally configure this in the Base Model:
import { Model as BaseModel } from 'vue-api-query'
export default class Model extends BaseModel {
// Define a base url for a REST API
baseURL() {
return 'http://my-api.com'
}
// Implement a default request method
request(config) {
return this.$http.request(config)
}
// Override default query parameter names
parameterNames() {
const defaultParams = super.parameterNames()
const customParams = {
include: 'include_custom'
}
return { ...defaultParams, ...customParams }
}
// Configure qs
stringifyOptions() {
return {
arrayFormat: 'indices'
}
}
}
Configuring FormData
See the API reference and object-to-formdata
When uploading files, the data of our request will be automatically converted to FormData
using object-to-formdata
.
If needed, we can easily configure the options by overriding the formData
method.
We can globally configure this in the Base Model:
import { Model as BaseModel } from 'vue-api-query'
export default class Model extends BaseModel {
// Define a base url for a REST API
baseURL() {
return 'http://my-api.com'
}
// Implement a default request method
request(config) {
return this.$http.request(config)
}
// Override default query parameter names
parameterNames() {
const defaultParams = super.parameterNames()
const customParams = {
include: 'include_custom'
}
return { ...defaultParams, ...customParams }
}
// Configure qs
stringifyOptions() {
return {
arrayFormat: 'indices'
}
}
// Configure object-to-formadata
formData() {
return {
indices: true
}
}
}