Collection
While the Model
class provides an eloquent way to manage a single Model, the Collection
class provides way of managing a collection (array) of models.
That is a difference from the Laravel way because on the front end you would typically have different components for handling a single Model
or a Collection
of models.
Create a Collection Class
Create a PostCollection
class that extends the default Collection
class. Note we're using the PostApi
created previously.
Example
import { Collection } from '@konnec/vue-eloquent'
import PostApi from './PostApi'
import { IPost } from './IPost'
import { reactive } from 'vue'
export default class PostCollection extends Collection {
api = PostApi
// Note that data should be a reactive array
data = reactive<IPost[]>([])
constructor(posts?: IPost[]){
super()
// The factory method is only required if you choose to create an instance
// from an existing IPost array
super.factory(posts)
}
}
You can then access the collection from the data
attribute.
<script lang="ts">
import PostsCollection from './Post'
export default defineComponent({
data() {
return {
posts: new PostCollection(),
}
},
created: {
// this will fetch all posts from the API and instantiate them to
// this.posts.data attribute
this.posts.get()
}
})
</script>
Eloquent Api
Filtering
// Chaining several where clauses
this.posts.where({ author_id: 1 }).where({ title: 'Tech' }).get()
// OR, passing multiple parameters to single where clause
this.posts.where({ author_id: 1, title: 'Tech' }).get()
Relationships
// Requesting both `author` and `comments` relationships to be added to the response.
this.posts.with(['author', 'comments']).get()
Attributes
// Views attribute will be added to the response
this.posts.append(['views']).get()
Select
// Requesting only post id and title from the API
this.posts.select(['id', 'title']).get()
Sorting
// Sorting `author_id` ascending.
this.posts.sort(['author_id']).get()
// OR
// Sorting `author_id` ascending and then title in descending order.
this.posts.sort(['+author_id','-title']).get()
States
The Collection
has 3 states which are available and updated during the API requests. You can use them to display state changes on you UI, e.g. a loading
indicator on a button
state: {
isLoading: boolean,
isSucess: boolean,
isError: boolean
}
Broadcast
Vue Eloquent
uses Laravel Echo
for broadcasting. After defining the channel name on your Collection you have to initialize the broadcasting on your component.
Firstly you need to pass your Laravel Echo
instance to the package:
import { createBroadcast } from '@konnec/vue-eloquent'
import Echo from 'laravel-echo'
const broadcast: Echo = ((<any>window).Echo = new Echo({
// your configuration here
}))
createBroadcast(broadcast)
Then you need to define the channel name on your collection class
import { Collection } from '@konnec/vue-eloquent'
import PostApi from './PostApi'
import { IPost } from './IPost'
import { reactive } from 'vue'
export default class PostCollection extends Collection {
api = PostApi
protected channel = 'posts'
data = reactive<IPost[]>([])
constructor(posts?: IPost[]){
super()
super.factory(posts)
}
}
<script lang="ts">
import PostsCollection from './Post'
export default defineComponent({
data() {
return {
posts: new PostsCollection(),
}
},
created: {
this.initBroadcast()
// this will fetch all posts from the API and instantiate them to
// this.posts.data attribute
this.posts.get()
}
})
</script>
Alternatively you can pass a new channel directly to the broadcast constructor:
this.initBroadcast('posts')
Broadcast Observers
broadcastCreated(e: any)
broadcastUpdated(e: any)
broadcastDeleted(e: any)
Broadcast Observers are a good place to subscribe to broadcast events and update your Collection
accordingly.
import { reactive } from 'vue'
import { Collection } from '../src/index'
import PostApi from './PostApi'
import { IPost } from './PostInterface'
export default class PostsCollection extends Collection {
protected api = PostApi
protected channel = 'posts'
public data = reactive<IPost[]>([])
constructor(posts?: IPost[]){
super()
super.factory(posts)
}
protected async broadcastCreated(e: any): Promise<{ data: IPost }>
{
// add new post to the collection
const newPost = await this.api.show(e.id)
this.data.push(newPost)
}
}