Skip to content

Examples ​

These examples are also available in the package's examples folder.

Setup ​

ts
import Auth from './examples/Auth'
import { createHttp, VueEloquentPlugin } from '@konnec/vue-eloquent'

/**
 * Create your auth class to handle the authentication endpoints
 * The Auth class should extend the package's default Auth class
 */
const auth = new Auth()

/**
 * Create an instance of the HTTP service.
 */
const http = createHttp({
    baseURL: 'http://localhost:9000',
    apiPrefix: 'api/v1',
    bearerToken: auth.token,
})

/**
 * Optional: Vue DevTools support
 */
app.use(VueEloquentPlugin)

Interfaces ​

ts
import type { ModelParams } from '@konnec/vue-eloquent'
import type { IUser } from './UserInterface'
import type { IComment } from './CommentInterface'

export interface IPost extends ModelParams {
  title: string | undefined
  description: string | undefined
  author_id: number | undefined
  author?: IUser | undefined
  comments?: IComment[] | undefined
}

Api Class ​

ts
import { Api } from '@konnec/vue-eloquent'

export default class PostApi extends Api {
    protected override resource = 'posts'

    protected override dates = [
        'created_at',
        'updated_at',
        'deleted_at',
        'author.created_at'
    ]

    constructor() {
        super()
    }
}

Model ​

ts
import { required } from '@vuelidate/validators'
import { computed, reactive } from 'vue'
import { Model } from '@konnec/vue-eloquent'
import PostApi from './PostApi'
import type { IPost } from './PostInterface'
import UserApi from './UserApi'
import type { IUser } from './UserInterface'
import CommentApi from './CommentApi'
import type { IComment } from './CommentInterface'

export default class Post extends Model<IPost> {
  override api = PostApi

  override model = reactive({
    id: undefined,
    created_at: undefined,
    updated_at: undefined,
    deleted_at: undefined,
    author_id: undefined,
    title: undefined,
    description: undefined,
    author: {} as IUser,
    comments: [] as IComment[],
  }) as unknown as IPost

  protected override parameters = {
    title: 'New Post',
  }

  constructor(post?: IPost) {
    super()
    super.factory(post)
    super.initValidations()
  }

  protected override validations = computed(() => ({
    model: {
      title: {
        required
      },
      description: { required },
    }
  }))

  async author(): Promise<IUser> {
    return await this.hasOne(UserApi, this.model.author_id as number)
  }

  comments() {
    return this.hasMany(CommentApi, this.model.id as number)
  }
}

Collection ​

ts
import { reactive } from 'vue'
import { Collection } from '@konnec/vue-eloquent'
import PostApi from './PostApi'
import type { IPost } from './PostInterface'

export default class PostsCollection extends Collection {
  override api = PostApi

  protected override channel = 'posts'

  override data = reactive<IPost[]>([])

  constructor(posts?: IPost[]) {
    super()
    if (posts) super.factory(posts)
  }

  protected override async broadcastCreated(e: any): Promise<void> {
    // add new post to the collection
    const newPost = await this.api.show<IPost>(e.id)
    this.data.push(newPost.data)
  }
}

Policy ​

ts
import { Policy } from '@konnec/vue-eloquent'

export default class Acl extends Policy {
  constructor(acl?: any) {
    super(acl)
  }
}

Usage ​

Form Component ​

vue
<template>
  <q-card style="width: 400px; max-width: 100%">
    <q-card-section class="bg-primary">
      <span class="text-white text-h6">My Post</span>
    </q-card-section>
    <q-form @submit="onSubmit">
      <q-card-section>
        <div class="row">
          <div class="col"><q-input v-show="false" v-model="post.model.id" label="ID" /></div>
        </div>
        <div class="row">
          <div class="col">
            <q-input
              v-model="post.model.title"
              :error="post.$model.title.$error"
              :error-message="post.$model.title.$errors[0]?.$message"
              label="Title"
            />
          </div>
        </div>
        <div class="row">
          <div class="col"><q-input v-model="post.model.description" label="Description" /></div>
        </div>
      </q-card-section>
      <q-card-actions>
        <q-space />
        <q-btn label="Submit" :loading="post.state.isLoading" type="submit" />
      </q-card-actions>
    </q-form>
  </q-card>
</template>

<script lang="ts">
import Post from './Post'
import type { PropType } from 'vue'
import { defineComponent } from 'vue'
import { Action } from '@konnec/vue-eloquent'

export default defineComponent({
  props: {
    postId: {
      required: true,
      type: Number,
      default: 0
    },
    action: {
      required: true,
      type: String as PropType<Action>
    }
  },
  emits: ['close', 'created', 'updated'],
  data() {
    return {
      post: new Post()
    }
  },
  async created() {
    // Using the same form to CREATE, VIEW OR EDIT a Post
    if (this.action !== Action.CREATE) {
      this.post = await Post.find(this.postId)
    }
  },
  methods: {
    async onSubmit() {
      // Validate the form. Display error messages if invalid, or continue to submitting
      if (!this.post.$validate()) return

      const { actioned, model } = await this.post.save()
      this.$emit(actioned, model)
      this.$emit('close')
    }
  }
})
</script>

Collection Component ​

vue
<template>
  <q-page>

    <span class="text-white text-h6">Posts Page</span>

    <div class="row">
      <!--  Display your posts here: posts.data -->
    </div>

    <q-dialog v-model="open">
      <post-form
        :action="action"
        :post-id="postId"
        @close="open = false"
        @created="onCreated"
        @updated="onUpdated" />
    </q-dialog>

  </q-page>
</template>

<script lang="ts">
import PostsCollection from './PostsCollection'
import { defineComponent } from 'vue'
import PostForm from './PostForm.vue'
import { Action } from '@konnec/vue-eloquent'

export default defineComponent({
  components: {
    PostForm
  },
  data() {
    return {
      posts: new PostsCollection(),
      open: false,
      action: Action.CREATE as Action,
      postId: 0,
    }
  },
  created() {
    this.posts.joinChannel()
    this.posts.where({ author_id: 1 }).get()
  },
  methods: {
    onCreated(args: IPost) {
      // do something
    },
    onUpdated(args: IPost) {
      // do something
    },
  },
})
</script>