Skip to content

Crud Create/Update

z-crud component create and edit form functionality introduction.

Basic Usage

Configure add or edit fields in column to implement create or edit form configuration.

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

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

interface FormData {
  name: string
  gender: string
  age: string
}

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    add: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
    edit: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    add: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
    edit: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    add: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    edit: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const searchFormConfig = ref({
  labelWith: '80px',
  columns: [
    {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
    {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
    {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  ],
})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  addApi: commonApi,
  editApi: commonApi,
})

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

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

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

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

Configure columns field in add and edit to implement create and edit form configuration.

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

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

interface FormData {
  name: string
  gender: string
  age: string
}

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
  },
  {
    prop: 'gender',
    label: 'Gender',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const searchFormConfig = ref({
  labelWith: '80px',
  columns: [
    {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
    {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
    {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  ],
})

const addFormConfig = ref({
  columns: [
    {
      component: 'input',
      label: 'Name (create)',
      field: 'name',
    },
    {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
    {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  ],
})

const editFormConfig = ref({
  columns: [
    {
      component: 'input',
      label: 'Name (edit)',
      field: 'name',
    },
    {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
    {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  ],
})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  addApi: commonApi,
  editApi: commonApi,
})

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

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

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

<template>
  <z-crud
    v-model:pagination="pagination"
    v-model:data="tableData"
    v-model:formData="formData"
    v-model:loading="loading"
    :columns="columns"
    :options="options"
    :search="searchFormConfig"
    :request="request"
    :detail="false"
    :add="addFormConfig"
    :edit="editFormConfig"
  />
</template>

Configure columns field in form to implement both create and edit form configuration, but it will also configure query and detail information at the same time. You can configure search and detail as false to disable them.

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

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

interface FormData {
  name: string
  gender: string
  age: string
}

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
  },
  {
    prop: 'gender',
    label: 'Gender',
  },
  {
    prop: 'age',
    label: 'Age',
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const searchFormConfig = ref({
  labelWith: '80px',
  columns: [
    {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
    {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
    {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  ],
})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  addApi: commonApi,
  editApi: commonApi,
})

const formConfig = ref({
  columns: [
    {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
    {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
    {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
  ],
})

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

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

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

<template>
  <z-crud
    v-model:pagination="pagination"
    v-model:data="tableData"
    v-model:formData="formData"
    v-model:loading="loading"
    :columns="columns"
    :options="options"
    :search="searchFormConfig"
    :form="formConfig"
    :request="request"
    :detail="false"
  />
</template>

Configure form field in column items to implement create and edit form configuration, but it will also configure query form at the same time. You can set search as false to disable it.

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

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

interface FormData {
  name: string
  gender: string
  age: string
}

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    search: false,
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  addApi: commonApi,
  editApi: commonApi,
})

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

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

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

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

Confirm API

Configure addApi and editApi in request.

editApi will pass an additional rowKey parameter, default is id.

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

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

interface FormData {
  name: string
  gender: string
  age: string
}

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    search: false,
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  addApi: commonApi,
  editApi: commonApi,
})

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

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

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

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

If create and edit APIs are the same, you can configure submitApi. When editing, it will also include rowKey.

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

interface FormData {
  name?: string
  gender?: string
  age?: string
}

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

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    search: false,
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  submitApi: commonApi,
})

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

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

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

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

Edit Detail Data

Configure detailApi in request to get default data for edit dialog from API.

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

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

interface FormData {
  name: string
  gender: string
  age: string
}

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    search: false,
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  addApi: commonApi,
  editApi: commonApi,
  detailApi,
})

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

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

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

function detailApi(params: { id: number }) {
  console.log(JSON.stringify(params), 'detailApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        data: {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: ['2020-01-01', '2020-01-03'],
        },
      })
    }, 100)
  })
}
</script>

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

Detail Data Processing

If you need to process the detail data returned by the API, you can configure request.alias.detail. Passing a function supports custom detail data, passing a string supports custom data path.

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

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

interface FormData {
  name: string
  gender: string
  age: string
}

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

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref<RowData[]>([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    search: false,
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  addApi: commonApi,
  editApi: commonApi,
  detailApi,
  alias: {
    detail: (res: GetTableDataRes) => {
      console.log(res, 'res')
      return {
        ...res.data,
        time: [],
      }
    },
  },
})

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

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

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

function detailApi(params: { id: number }) {
  console.log(JSON.stringify(params), 'detailApi params')
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        data: {
          id: 1,
          name: 'Steven',
          gender: 'male',
          age: 22,
          time: ['2020-01-01', '2020-01-03'],
        },
      })
    }, 100)
  })
}
</script>

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

Custom Confirmation

When request doesn't configure submitApi, addApi and editApi, there will be operate-submit event.

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

interface FormData {
  name?: string
  gender?: string
  age?: string
}

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

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    search: false,
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
})

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

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

function handleSubmit({ done, formRef, formData, type, confirmButtonLoading, row, invalidFields }: DialogFormSubmitParams<FormData, RowData>) {
  confirmButtonLoading.value = true
  console.log(formRef, formData, type, invalidFields, row)
  done()
  confirmButtonLoading.value = false
}
</script>

<template>
  <z-crud
    v-model:pagination="pagination"
    v-model:data="tableData"
    v-model:formData="formData"
    v-model:loading="loading"
    :columns="columns"
    :options="options"
    :detail="false"
    :request="request"
    @operate-submit="handleSubmit"
  />
</template>

Custom Cancel

operate-cancel custom cancel event. If the component is not configured, clicking cancel will close by default.

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

interface FormData {
  name?: string
  gender?: string
  age?: string
}

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

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    form: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    form: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    form: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    search: false,
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
})

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

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

function handleSubmit({ done, formRef, formData, type, confirmButtonLoading, row, invalidFields }: DialogFormSubmitParams<FormData, RowData>) {
  confirmButtonLoading.value = true
  console.log(formRef, formData, type, invalidFields, row)
  done()
  confirmButtonLoading.value = false
}
</script>

<template>
  <z-crud
    v-model:pagination="pagination"
    v-model:data="tableData"
    v-model:formData="formData"
    v-model:loading="loading"
    :columns="columns"
    :options="options"
    :detail="false"
    :request="request"
    @operate-submit="handleSubmit"
  />
</template>

Form Properties

Use add and edit objects to configure create and edit form properties. The form property can uniformly configure create and edit.

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

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

interface FormData {
  name: string
  gender: string
  age: string
}

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    add: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
    edit: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    add: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
    edit: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    add: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    edit: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const searchFormConfig = ref({
  labelWith: '80px',
  columns: [
    {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
    {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
    {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  ],
})

const addFormConfig = ref({
  labelWidth: '120px',
  labelPosition: 'top',
})

const editFormConfig = ref({
  labelWidth: '80px',
  labelPosition: 'left',
})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  addApi: commonApi,
  editApi: commonApi,
})

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

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

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

<template>
  <z-crud
    v-model:pagination="pagination"
    v-model:data="tableData"
    v-model:formData="formData"
    v-model:loading="loading"
    :columns="columns"
    :options="options"
    :search="searchFormConfig"
    :add="addFormConfig"
    :edit="editFormConfig"
    :detail="false"
    :request="request"
  />
</template>

Dialog Properties

You can use the dialog object to uniformly configure create and edit dialog properties, or use add.dialog and edit.dialog to configure dialog properties separately.

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

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

interface FormData {
  name: string
  gender: string
  age: string
}

const loading = ref(false)
const formData = ref({
  name: '',
  gender: '',
  age: '',
})
const tableData = ref([])

const columns = ref([
  {
    prop: 'name',
    label: 'Name',
    add: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
    edit: {
      component: 'input',
      field: 'name',
      label: 'Name',
      required: true,
    },
  },
  {
    prop: 'gender',
    label: 'Gender',
    add: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
    edit: {
      component: 'select',
      field: 'gender',
      label: 'Gender',
    },
  },
  {
    prop: 'age',
    label: 'Age',
    add: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
    edit: {
      component: 'el-date-picker',
      field: 'time',
      label: 'Date',
      fieldProps: {
        type: 'daterange',
        startPlaceholder: 'Start date',
        endPlaceholder: 'End date',
      },
    },
  },
  {
    prop: 'date',
    label: 'Date',
  },
])

const searchFormConfig = ref({
  labelWith: '80px',
  columns: [
    {
      component: 'input',
      label: 'Name',
      field: 'name',
    },
    {
      component: 'select',
      label: 'Gender',
      field: 'gender',
    },
    {
      component: 'input',
      label: 'Age',
      field: 'age',
    },
  ],
})

const addFormConfig = ref({
  labelWidth: '120px',
  labelPosition: 'top',
  dialog: {
    title: 'Create Dialog',
  },
})

const editFormConfig = ref({
  labelWidth: '80px',
  labelPosition: 'left',
  dialog: {
    title: 'Edit Dialog',
  },
})

const options = {
  gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
const pagination = ref({
  page: 1,
  pageSize: 2,
  total: 4,
})
const request = ref({
  searchApi: mockApi,
  addApi: commonApi,
  editApi: commonApi,
})

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

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

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

<template>
  <z-crud
    v-model:pagination="pagination"
    v-model:data="tableData"
    v-model:formData="formData"
    v-model:loading="loading"
    :columns="columns"
    :options="options"
    :search="searchFormConfig"
    :add="addFormConfig"
    :edit="editFormConfig"
    :detail="false"
    :request="request"
  />
</template>
AttributeDescriptionTypeDefault
detailDetail configurationboolean / object / ({ row, tableRef }) => voidtrue
formSearch, add, edit and view form attribute configurationobject
actionWhether to show action items (built-in delete, edit buttons)booleantrue
editEdit configurationboolean / objecttrue
addAdd configurationboolean / objecttrue
deleteDelete configurationboolean / ({ row, tableRef, getTableData }) => void / object
searchSearch configurationboolean / objecttrue
requestAPI configurationobject

add and edit Attributes

AttributeDescriptionTypeDefault
dialogel-dialog component attributesobject
rulesForm validation rulesobject
columnsForm itemsarray
optionsForm option data sourceobject
colonForm item colonbooleanfalse
alignVertical alignment under flex layouttop / middle /bottom
label-positionPosition of form field labels. When set to left or right, you also need to set the label-width attributeenumright
label-widthWidth of labels, e.g. '50px'. Form items that are direct children of Form will inherit this value. auto can be used.string / number''
label-suffixSuffix for form field labelsstring''
hide-required-asteriskWhether to hide the red asterisk next to required field labels.booleanfalse
require-asterisk-positionPosition of asterisk.left / rightleft
show-messageWhether to show validation error messagesbooleantrue
inline-messageWhether to display validation messages inlinebooleanfalse
status-iconWhether to display validation result feedback icons in input boxesbooleanfalse
validate-on-rule-changeWhether to trigger validation immediately after the rules attribute changesbooleantrue
sizeSize for controlling components within this formlarge / default / small
disabledWhether to disable all components in this form. If set to true, it will override the disabled attribute of internal componentsbooleanfalse
scroll-to-errorWhen validation fails, scroll to the first error form itembooleanfalse
scroll-into-view-optionsWhen validation has failed results, scroll to the first failed form itemobject / boolean

form Attributes

AttributeDescriptionTypeDefault
rulesForm validation rulesobject
columnsForm itemsarray
optionsForm option data sourceobject
colonForm item colonbooleanfalse
alignVertical alignment under flex layouttop / middle /bottom
label-positionPosition of form field labels. When set to left or right, you also need to set the label-width attributeenumright
label-widthWidth of labels, e.g. '50px'. Form items that are direct children of Form will inherit this value. auto can be used.string / number''
label-suffixSuffix for form field labelsstring''
hide-required-asteriskWhether to hide the red asterisk next to required field labels.booleanfalse
require-asterisk-positionPosition of asterisk.left / rightleft
show-messageWhether to show validation error messagesbooleantrue
inline-messageWhether to display validation messages inlinebooleanfalse
status-iconWhether to display validation result feedback icons in input boxesbooleanfalse
validate-on-rule-changeWhether to trigger validation immediately after the rules attribute changesbooleantrue
sizeSize for controlling components within this formlarge / default / small
disabledWhether to disable all components in this form. If set to true, it will override the disabled attribute of internal componentsbooleanfalse
scroll-to-errorWhen validation fails, scroll to the first error form itembooleanfalse
scroll-into-view-optionsWhen validation has failed results, scroll to the first failed form itemobject / boolean

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
Event NameDescriptionType
operate-submitDialog confirm({ done, formRef, formData, type, confirmButtonLoading, row, invalidFields }) => void
operate-cancelDialog cancel({ done, formRef, formData, type, confirmButtonLoading, row }) => void

Released under the MIT License.