Skip to content

Crud API

Integrates z-form and z-table components to implement CRUD functionality.

Table API

Configure searchApi, deleteApi, addApi, editApi in request to directly implement table data retrieval, data deletion, data creation and editing operations.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const request = ref({
  searchApi: getTableData,
  deleteApi: commonApi,
  submitApi: commonApi,
})
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const formData = ref({})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}

function getTableData(params: any) {
  console.log(params, 'getTableData params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: '2020-01-01',
        },
        {
          id: 2,
          name: 'Helen',
          gender: 'male',
          age: 12,
          time: '2012-01-01',
        },
        {
          id: 3,
          name: 'Nancy',
          gender: 'female',
          age: 18,
          time: '2018-01-01',
        },
        {
          id: 4,
          name: 'Jack',
          gender: 'male',
          age: 28,
          time: '2028-01-01',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function commonApi(params: any) {
  console.log(JSON.stringify(params), 'commonApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        msg: 'success',
        code: 200,
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:formData="formData"
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :options="options"
    :columns="columns"
    :request="request"
  />
</template>

Table Data API Configuration

Configure the alias field in request to customize data paths, defaults to data.list and data.total.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'

interface RowData {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const request = ref({
  searchApi: getTableData,
  deleteApi: commonApi,
  submitApi: commonApi,
  detailApi,
  alias: {
    list: 'result.data',
    total: 'result.all',
  },
})
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const formData = ref({})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}

function getTableData(params: any) {
  console.log(params, 'getTableData params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: '2020-01-01',
        },
        {
          id: 2,
          name: 'Helen',
          gender: 'male',
          age: 12,
          time: '2012-01-01',
        },
        {
          id: 3,
          name: 'Nancy',
          gender: 'female',
          age: 18,
          time: '2018-01-01',
        },
        {
          id: 4,
          name: 'Jack',
          gender: 'male',
          age: 28,
          time: '2028-01-01',
        },
      ]

      resolve({
        result: {
          page: 1,
          pageSize: 2,
          all: 4,
          data: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function commonApi(params: any) {
  console.log(JSON.stringify(params), 'commonApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        msg: 'success',
        code: 200,
      })
    }, 100)
  })
}

function detailApi({ id, row }: { id: number, row: RowData }) {
  console.log(id, row, 'detailApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        data: {
          id: 3,
          name: 'Nancy',
          gender: 'female',
          age: 18,
          time: '2018-01-01',
        },
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:formData="formData"
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :options="options"
    :columns="columns"
    :request="request"
  />
</template>

Supports passing functions for custom returns.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'

interface RowData {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

interface GetTableDataRes { result: { page: number, pageSize: number, data: RowData[], all: number } }

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const request = ref({
  searchApi: getTableData,
  deleteApi: commonApi,
  submitApi: commonApi,
  alias: {
    list: (res: GetTableDataRes) => res.result.data,
    total: (res: GetTableDataRes) => res.result.all,
  },
})
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const formData = ref({})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}

function getTableData(params: any): Promise<GetTableDataRes> {
  console.log(params, 'getTableData params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: '2020-01-01',
        },
        {
          id: 2,
          name: 'Helen',
          gender: 'male',
          age: 12,
          time: '2012-01-01',
        },
        {
          id: 3,
          name: 'Nancy',
          gender: 'female',
          age: 18,
          time: '2018-01-01',
        },
        {
          id: 4,
          name: 'Jack',
          gender: 'male',
          age: 28,
          time: '2028-01-01',
        },
      ]

      resolve({
        result: {
          page: 1,
          pageSize: 2,
          all: 4,
          data: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function commonApi(params: any) {
  console.log(JSON.stringify(params), 'commonApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        msg: 'success',
        code: 200,
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:formData="formData"
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :options="options"
    :columns="columns"
    :request="request"
  />
</template>

Custom Table Data Method

Supports customizing table data method through request.searchFunc.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'

interface RowData {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

interface GetTableDataRes { data: { page: number, pageSize: number, list: RowData[], total: number } }

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const tableData = ref<RowData[]>([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const formData = ref({})
const request = ref({
  deleteApi: commonApi,
  submitApi: commonApi,
  searchFunc: async ({ params }: any) => {
    loading.value = true
    try {
      console.log(params, 'searchFunc params')
      const res = await getData(params)
      tableData.value = res.data.list
      pagination.value.total = res.data.total
    }
    catch {

    }
    loading.value = false
  },
})
const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}

function getData(params: any): Promise<GetTableDataRes> {
  console.log(params, 'params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: '2020-01-01',
        },
        {
          id: 2,
          name: 'Helen',
          gender: 'male',
          age: 12,
          time: '2012-01-01',
        },
        {
          id: 3,
          name: 'Nancy',
          gender: 'female',
          age: 18,
          time: '2018-01-01',
        },
        {
          id: 4,
          name: 'Jack',
          gender: 'male',
          age: 28,
          time: '2028-01-01',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function commonApi(params: any) {
  console.log(JSON.stringify(params), 'commonApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        msg: 'success',
        code: 200,
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:formData="formData"
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :options="options"
    :columns="columns"
    :request="request"
  />
</template>

Table Data Processing

Supports secondary processing of table data through request.tableData.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'

interface RowData {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const formData = ref({})
const request = ref({
  searchApi: getData,
  deleteApi: commonApi,
  submitApi: commonApi,
  tableData: (data: RowData[]) => {
    return data.map((item, index) => ({
      ...item,
      name: item.name + index,
    }))
  },
})
const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}

function getData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: '2020-01-01',
        },
        {
          id: 2,
          name: 'Helen',
          gender: 'male',
          age: 12,
          time: '2012-01-01',
        },
        {
          id: 3,
          name: 'Nancy',
          gender: 'female',
          age: 18,
          time: '2018-01-01',
        },
        {
          id: 4,
          name: 'Jack',
          gender: 'male',
          age: 28,
          time: '2028-01-01',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function commonApi(params: any) {
  console.log(JSON.stringify(params), 'commonApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        msg: 'success',
        code: 200,
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:formData="formData"
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :options="options"
    :columns="columns"
    :request="request"
  />
</template>

Callbacks

Supports doing things before and after getting table data through request.beforeData and request.afterData.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'

interface RowData {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

interface GetTableDataRes { data: { page: number, pageSize: number, list: RowData[], total: number } }

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const formData = ref({})
const request = ref({
  searchApi: getData,
  deleteApi: commonApi,
  submitApi: commonApi,
  beforeData: async () => {
    await delay(100)
    console.log('beforeData')
  },
  afterData: (res: GetTableDataRes) => {
    console.log(res, 'afterData')
  },
})
const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}

function delay(time: number) {
  return new Promise((resolve) => {
    setTimeout(resolve, time)
  })
}

function getData(): Promise<GetTableDataRes> {
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: '2020-01-01',
        },
        {
          id: 2,
          name: 'Helen',
          gender: 'male',
          age: 12,
          time: '2012-01-01',
        },
        {
          id: 3,
          name: 'Nancy',
          gender: 'female',
          age: 18,
          time: '2018-01-01',
        },
        {
          id: 4,
          name: 'Jack',
          gender: 'male',
          age: 28,
          time: '2028-01-01',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function commonApi(params: any) {
  console.log(JSON.stringify(params), 'commonApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        msg: 'success',
        code: 200,
      })
    }, 100)
  })
}
</script>

<template>
  <z-crud
    v-model:formData="formData"
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :options="options"
    :columns="columns"
    :request="request"
  />
</template>

Internal Methods

Supports calling the getTableData method again from outside the table.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const tableData = ref([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const formData = ref({})
const request = ref({
  searchApi: getData,
  deleteApi: commonApi,
  submitApi: commonApi,
})
const crud = ref()
const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}

function getData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: '2020-01-01',
        },
        {
          id: 2,
          name: 'Helen',
          gender: 'male',
          age: 12,
          time: '2012-01-01',
        },
        {
          id: 3,
          name: 'Nancy',
          gender: 'female',
          age: 18,
          time: '2018-01-01',
        },
        {
          id: 4,
          name: 'Jack',
          gender: 'male',
          age: 28,
          time: '2028-01-01',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function commonApi(params: any) {
  console.log(JSON.stringify(params), 'commonApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        msg: 'success',
        code: 200,
      })
    }, 100)
  })
}

function handleClick() {
  crud.value.getTableData()
}
</script>

<template>
  <el-button @click="handleClick">
    click
  </el-button>
  <z-crud
    ref="crud"
    v-model:formData="formData"
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :options="options"
    :columns="columns"
    :request="request"
  />
</template>

Custom Operations

If you need custom operations, you can use events like refresh, search, reset, submit, delete to implement refresh, query, reset and delete operations.

<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { CrudDeleteDialogConfirmParams, Pagination } from 'ideaz-element'

interface RowData {
  id: number
  name: string
  gender: string
  age: number
  time: string
}

interface GetTableDataRes { data: { page: number, pageSize: number, list: RowData[], total: number } }

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      label: 'Name',
      field: 'name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  },
  {
    prop: 'time',
    label: 'Date',
  },
])
const tableData = ref<RowData[]>([])
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 0,
})
const loading = ref(false)
const formData = ref({})
const dialog = ref({
  confirmButtonLoading: false,
})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}

function getData(params: any): Promise<GetTableDataRes> {
  console.log(params, 'params')
  return new Promise((resolve) => {
    setTimeout(() => {
      const data = [
        {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: '2020-01-01',
        },
        {
          id: 2,
          name: 'Helen',
          gender: 'male',
          age: 12,
          time: '2012-01-01',
        },
        {
          id: 3,
          name: 'Nancy',
          gender: 'female',
          age: 18,
          time: '2018-01-01',
        },
        {
          id: 4,
          name: 'Jack',
          gender: 'male',
          age: 28,
          time: '2028-01-01',
        },
      ]

      resolve({
        data: {
          page: 1,
          pageSize: 2,
          total: 4,
          list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
        },
      })
    }, 100)
  })
}

function commonApi(params: any) {
  console.log(JSON.stringify(params), 'commonApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        msg: 'success',
        code: 200,
      })
    }, 100)
  })
}

async function getTableData() {
  loading.value = true
  try {
    const params = {
      ...pagination.value,
      ...formData.value,
    }
    const res = await getData(params)
    tableData.value = res.data.list
    pagination.value.total = res.data.total
  }
  catch (error) {
    console.log(error)
  }
  loading.value = false
}

function handleRefresh(val: Pagination) {
  pagination.value.page = val.page!
  pagination.value.pageSize = val.pageSize!
  getTableData()
}

function handleSearch() {
  pagination.value.page = 1
  getTableData()
}

function handleDelete() {
  window.ZDialogTip({
    type: 'warning',
    message: 'Are you sure you want to delete this record?',
    title: 'Warning',
    onConfirm: ({ done, confirmButtonLoading }: CrudDeleteDialogConfirmParams<RowData>) => {
      confirmButtonLoading.value = true
      done()
      confirmButtonLoading.value = false
    },
  })
}

async function handleSubmit({ formData, type, rowData, formRef, done, isValid }: { formData: any, type: 'add' | 'edit', rowData: RowData, formRef: any, done: () => void, isValid: boolean }) {
  if (isValid) {
    dialog.value.confirmButtonLoading = true
    try {
      const params = {
        ...formData,
      }
      console.log(params, rowData, formRef, 'params')
      if (type === 'edit')
        await commonApi({ ...params, id: rowData.id })
      else
        await commonApi(params)
      dialog.value.confirmButtonLoading = false
      done()
      getTableData()
    }
    catch {

    }
    dialog.value.confirmButtonLoading = false
  }
}

getTableData()
</script>

<template>
  <z-crud
    v-model:formData="formData"
    v-model:data="tableData"
    v-model:pagination="pagination"
    v-model:loading="loading"
    :options="options"
    :columns="columns"
    :dialog="dialog"
    @refresh="handleRefresh"
    @reset="handleSearch"
    @search="handleSearch"
    @submit="handleSubmit"
    @delete="handleDelete"
  />
</template>

request Attributes

AttributeDescriptionTypeDefault
searchApiSearch API(params: any) => promise
submitApiEdit and create confirmation({ [key: string]: any, row: any, type: 'add' / 'edit' / 'view', formData: any }) => promise
deleteApiDelete API({ [key: string]?: any, row?: any, selectionData?: any }) => promise
addApiCreate API({ type: 'add' / 'edit' / 'view', formData: any }) => promise
editApiEdit API({ [key: string]: any, row: any, type: 'add' / 'edit' / 'view', formData: any }) => promise
detailApiDetail API({ [key: string]: any, row: any }) => promise
aliasCustom data pathobject
beforeDataCallback before table data API callFunction
afterDataCallback after table data API call(res) => void
searchFuncSearch method override({ params }) => any
tableDataCustom table data return(res) => any

alias Attributes

AttributeDescriptionTypeDefault
listTable data pathstring / (res) => arraydata.list
totalTable data total pathstring / (res) => numberdata.total

Released under the MIT License.