Crud

Crud is a multifunctional business component based on Table Form and Descriptions

Tip

It is best to familiarize yourself with these components Table Form Descriptions before using them

Use

Basic Use

When columns is bound to a reactive array, changes in the array will affect Crud changes (dynamic Crud). If you don’t need a dynamic Crud, it is recommended to bind an ordinary array.

Set add edit form hide search detail in columns attribute will automatic generate crud

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = [
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        add: true,
        edit: true,
        search: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
        add: true,
        search: true,
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        component: 'el-input',
        add: true,
        edit: true,
        detail: true,
      },
    ]
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = (done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    }

    const search = (done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    }

    const submit = (close, done, type, isValid, invalidFields) => {
      ElMessage(`submit: ${type}, ${isValid}`)
      console.log('submit', form.value, type, isValid, invalidFields)
      setTimeout(() => {
        isValid ? close() : done()
      }, 1000)
    }

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      detail,
      data,
      columns,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

Intellisense

Use the defineCrudColumns defineCrudMenuColumns defineCrudBeforeOpen defineCrudBeforeClose defineCrudSearch defineCrudSubmit to make it easier to define columns

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        add: true,
        edit: true,
        search: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
        add: true,
        search: true,
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        component: 'el-input',
        add: true,
        edit: true,
        detail: true,
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      columns,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

Nested value

Support for get or set the objects or arrays with nested structures value, only need to configure the prop

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudBeforeOpen,
  defineCrudSubmit,
  defineCrudSearch,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({ 'a.b': undefined })
    const serachForm = ref({ 'a.b': undefined })
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Break',
        prop: 'a.b',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
      {
        label: 'Object',
        prop: 'a.b.c',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
      {
        label: 'Array',
        prop: 'b[0]',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
    ])
    const data = [
      {
        'a.b': 'break nested value',
        a: { b: { c: 'nested value c' } },
        b: ['nested value in array'],
      },
    ]

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      } else {
        form.value = { 'a.b': undefined }
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      data,
      detail,
      columns,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

Custom Menu

By default, the add, edit, and delete buttons are not displayed, you need to config through the menu or use menu slot to display

Menu can also be configured through Localization

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="menu"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @search-reset="reset"
    @submit="submit"
    @reset="reset"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudMenuColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const menu = defineCrudMenuColumns({
      label: 'Operations',
      addText: 'New',
      detailText: 'View Row',
      editText: 'Edit Row',
      delText: 'Remove',
      searchText: 'Search',
      searchResetText: 'Reset Search',
      submitText: 'Create',
      resetText: 'Reset Form',
      detail: (row) => row.date !== '2016-05-02',
      edit: (row) => row.date !== '2016-05-03',
      del: (row) => row.date !== '2016-05-04',
      searchReset: false,
      detailProps: { type: 'success', plain: true },
      editProps: { type: 'default', plain: true },
      delProps: { type: 'info', plain: true },
    })
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        component: 'el-input',
        form: true,
        detail: true,
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-04',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-01',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      ElMessage('reset')
      console.log('reset')
    }

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      columns,
      menu,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      reset,
      deleteRow,
    }
  },
})
</script>

Set search-columns attribute to enable custom Search, same as Form columns

No Data
<template>
  <pro-crud
    v-model:search="serachForm"
    :columns="columns"
    :search-columns="searchColumns"
    @search="search"
    @search-reset="reset"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSearch,
  defineFormColumns,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const serachForm = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
      },
      {
        label: 'Name',
        prop: 'name',
      },
      {
        label: 'Address',
        prop: 'address',
      },
    ])
    const searchColumns = defineFormColumns([
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
      },
      {
        label: 'Date',
        prop: 'date',
        component: 'el-date-picker',
        props: {
          type: 'datetimerange',
          rangeSeparator: '-',
          startPlaceholder: 'start',
          endPlaceholder: 'end',
        },
      },
    ])

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const reset = () => {
      ElMessage('reset search')
      console.log('reset search')
    }

    return {
      serachForm,
      columns,
      searchColumns,
      search,
      reset,
    }
  },
})
</script>

Custom Add Form

Set add-columns attribute to enable custom Add Form, same as Form columns

No Data
<template>
  <pro-crud
    v-model="form"
    :columns="columns"
    :add-columns="addColumns"
    :menu="true"
    label-width="100px"
    @submit="submit"
    @reset="reset"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineFormColumns,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
      },
      {
        label: 'Name',
        prop: 'name',
      },
      {
        label: 'Address',
        prop: 'address',
      },
    ])
    const addColumns = defineFormColumns([
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
      },
      {
        label: 'Date',
        prop: 'date',
        component: 'el-date-picker',
        props: {
          type: 'datetimerange',
          rangeSeparator: '-',
          startPlaceholder: 'start',
          endPlaceholder: 'end',
        },
      },
    ])

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      ElMessage('reset')
      console.log('reset')
    }

    return {
      form,
      columns,
      addColumns,
      submit,
      reset,
    }
  },
})
</script>

Custom Edit Form

Set edit-columns attribute to enable custom Edit Form, same as Form columns

<template>
  <pro-crud
    v-model="form"
    :columns="columns"
    :edit-columns="editColumns"
    :menu="true"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @submit="submit"
    @reset="reset"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineFormColumns,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        add: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        detail: true,
      },
    ])
    const editColumns = defineFormColumns([
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
      },
      {
        label: 'Date',
        prop: 'date',
        component: 'el-date-picker',
        props: {
          type: 'datetimerange',
          rangeSeparator: '-',
          startPlaceholder: 'start',
          endPlaceholder: 'end',
        },
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      ElMessage('reset')
      console.log('reset')
    }

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      columns,
      detail,
      editColumns,
      data,
      beforeOpen,
      submit,
      reset,
      deleteRow,
    }
  },
})
</script>

Custom Form

Set form-columns attribute to enable custom Form, same as Form columns. It will act on both add and edit form

<template>
  <pro-crud
    v-model="form"
    :columns="columns"
    :form-columns="formColumns"
    :menu="true"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @submit="submit"
    @reset="reset"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineFormColumns,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        detail: true,
      },
    ])
    const formColumns = defineFormColumns([
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
      },
      {
        label: 'Date',
        prop: 'date',
        component: 'el-date-picker',
        props: {
          type: 'datetimerange',
          rangeSeparator: '-',
          startPlaceholder: 'start',
          endPlaceholder: 'end',
        },
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = {
          name: row.name,
          date: [],
        }
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      ElMessage('reset')
      console.log('reset')
    }

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      columns,
      formColumns,
      data,
      detail,
      beforeOpen,
      submit,
      reset,
      deleteRow,
    }
  },
})
</script>

Custom Detail

Set detail-columns attribute to enable custom Detail, same as Descriptions columns

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :detail-columns="detailColumns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
  defineDescriptionsColumns,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
      },
      {
        label: 'Name',
        prop: 'name',
      },
    ])
    const detailColumns = defineDescriptionsColumns([
      {
        label: 'Date',
        prop: 'date',
      },
      {
        label: 'Name',
        prop: 'name',
      },
      {
        label: 'Address',
        prop: 'address',
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      columns,
      detailColumns,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

Custom Table

Set table-columns attribute to enable custom Table, same as Table columns

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :table-columns="tableColumns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @submit="submit"
    @reset="reset"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineTableColumns,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        component: 'el-input',
        form: true,
        search: true,
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        component: 'el-input',
        detail: true,
      },
    ])
    const tableColumns = defineTableColumns([
      {
        label: 'Date',
        prop: 'date',
      },
      {
        label: 'User',
        children: [
          {
            label: 'Name',
            prop: 'name',
          },
          {
            label: 'Address',
            prop: 'address',
          },
        ],
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const reset = () => {
      console.log('reset')
    }

    const deleteRow = (row) => {
      console.log('deleteRow', row)
    }

    return {
      form,
      serachForm,
      columns,
      tableColumns,
      data,
      detail,
      beforeOpen,
      submit,
      reset,
      deleteRow,
    }
  },
})
</script>

Trigger Dialog

Set before-open or before-close attribute to enable perform an operation before Dialog is opened or before Dialog is closed

<template>
  <pro-crud
    v-model="form"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    :before-close="beforeClose"
    label-width="100px"
    @delete="deleteRow"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudBeforeOpen,
  defineCrudBeforeClose,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        detail: true,
      },
    ])
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      ElMessage(`beforeOpen: ${type}`)
      console.log('beforeOpen', type, row)
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const beforeClose = defineCrudBeforeClose((done) => {
      ElMessage('beforeClose')
      console.log('beforeClose')
      done()
    })

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      form,
      columns,
      data,
      detail,
      beforeOpen,
      beforeClose,
      deleteRow,
    }
  },
})
</script>

Open Dialog

By using the openDialog method exposed by the component, you can open the dialog

<template>
  <pro-crud
    ref="crudRef"
    v-model="form"
    :columns="columns"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
  >
    <template #menu-right="{ size }">
      <el-button
        :size="size"
        @click="crudRef.openDialog('add')"
      >
        open
      </el-button>
      <el-button
        :size="size"
        @click="crudRef.openDialog('edit', data[0])"
      >
        edit
      </el-button>
      <el-button
        :size="size"
        @click="crudRef.openDialog('detail', data[0])"
      >
        detail
      </el-button>
    </template>
    <template #form-menu-right="{ size }">
      <el-button
        :size="size"
        @click="crudRef.closeDialog()"
      >
        close
      </el-button>
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, ref } from 'vue'
import { defineCrudColumns, defineCrudBeforeOpen } from 'element-pro-components'

export default defineComponent({
  setup() {
    const crudRef = ref()
    const form = ref({})
    const detail = ref({})
    const columns = defineCrudColumns([
      {
        label: 'Date',
        prop: 'date',
        component: 'el-input',
        form: true,
        detail: true,
      },
      {
        label: 'Name',
        prop: 'name',
        detail: true,
      },
      {
        label: 'Address',
        prop: 'address',
        detail: true,
      },
    ])
    const data = [
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ]

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    return {
      crudRef,
      form,
      columns,
      data,
      detail,
      beforeOpen,
    }
  },
})
</script>

Slots

Use simple render-function by render in columns. or directly add some slot with [prop] in the template.

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    selection
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  >
    <template #menu-left="{ size }">
      <el-button
        :size="size"
        type="primary"
      >
        menu-left
      </el-button>
    </template>
    <template #menu-right="{ size }">
      <el-button
        :size="size"
        type="danger"
      >
        menu-right
      </el-button>
    </template>
    <template #menu="{ size }">
      <el-button
        :size="size"
        type="success"
        link
      >
        More
      </el-button>
    </template>
    <template #search-menu-right="{ size }">
      <el-button
        :size="size"
        type="success"
      >
        search-menu-right
      </el-button>
    </template>
    <template #action>
      <el-button
        :icon="Refresh"
        circle
        style="margin-right: 8px"
      />
      <pro-column-setting v-model="columns" />
    </template>
    <template #dialog-top="{ type }">
      <p style="text-align: center">
        dialog-top {{ type }}
      </p>
    </template>
    <template #dialog-bottom="{ type }">
      <p
        v-if="type === 'detail'"
        style="text-align: center"
      >
        only appears in the detail
      </p>
    </template>
    <template #form-name>
      <span>form slot</span>
    </template>
    <template #detail-name="{ item, size }">
      <el-tag :size="size">
        {{ item?.name }}
      </el-tag>
    </template>
    <template #table-name="{ row, size }">
      <el-tag :size="size">
        {{ row?.name }}
      </el-tag>
    </template>
    <template #table-name-header="{ column }">
      <s>{{ column.label }}</s>
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, h, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Clock, Refresh } from '@element-plus/icons-vue'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = ref(
      defineCrudColumns([
        {
          label: 'Date',
          prop: 'date',
          component: 'el-input',
          add: true,
          edit: true,
          search: true,
          detail: true,
          render: '--',
          props: {
            slots: {
              suffix: () =>
                h('span', { className: 'el-input__icon' }, h(Clock)),
            },
          },
        },
        {
          label: 'Name',
          prop: 'name',
          component: 'el-input',
          add: true,
          search: true,
          detail: true,
        },
        {
          label: 'Address',
          prop: 'address',
          component: 'el-input',
          add: true,
          edit: true,
          render: (row) => h('em', null, row.address),
        },
      ])
    )
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      Refresh,
      form,
      columns,
      serachForm,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

<style>
.el-input__icon {
  width: 14px;
}
</style>

Custom Form Content

Use crud-search crud-form slot to customize form content.

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    selection
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  >
    <template #crud-search="{ props }">
      <pro-form
        v-bind="props"
        :inline="false"
        label-width="100px"
        style="margin-bottom: 18px"
      />
    </template>
    <template #crud-form="{ props }">
      <pro-form
        v-bind="props"
        :inline="true"
      />
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = ref(
      defineCrudColumns([
        {
          label: 'Date',
          prop: 'date',
          component: 'el-input',
          add: true,
          edit: true,
          search: true,
          detail: true,
        },
        {
          label: 'Name',
          prop: 'name',
          component: 'el-input',
          add: true,
          search: true,
          detail: true,
        },
        {
          label: 'Address',
          prop: 'address',
          component: 'el-input',
          add: true,
          edit: true,
        },
      ])
    )
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      Refresh,
      form,
      columns,
      serachForm,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

<style>
.el-input__icon {
  width: 14px;
}
</style>

Custom Table Content

The component defaults to using ProTable to render the list, but for some special cases, using ProTable cannot better display the data. You can customize the list content through the crud-table slot.

qiang

address: No. 189, Grove St, Los Angeles

creation date: 2016-05-03

qiang

address: No. 189, Grove St, Los Angeles

creation date: 2016-05-02

  • 1
Go to
Total 2
<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    selection
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  >
    <template #crud-table="{ showMenu, createTableMenu }">
      <section class="list">
        <div
          v-for="item in data"
          :key="item.name"
          class="item"
        >
          <div class="item-content">
            <el-image
              :src="item.avatar"
              fit="cover"
              class="item-avatar"
            />
            <div class="item-info">
              <p class="name">
                {{ item.name }}
              </p>
              <p>address: {{ item.address }}</p>
              <p>creation date: {{ item.date }}</p>
            </div>
          </div>
          <div class="item-menu">
            <component
              :is="() => createTableMenu({ row: item })"
              v-if="showMenu"
            />
          </div>
        </div>
      </section>
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :total="total"
      />
    </template>
    <template #crud-detail>
      <div class="detail">
        <el-image
          :src="detail.avatar"
          fit="cover"
          class="item-avatar"
        />
        <div class="item-info">
          <p class="name">
            {{ detail.name }}
          </p>
          <p>address: {{ detail.address }}</p>
          <p>creation date: {{ detail.date }}</p>
        </div>
      </div>
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const currentPage = ref(1)
    const pageSize = ref(10)
    const total = ref(2)
    const detail = ref({})
    const columns = ref(
      defineCrudColumns([
        {
          label: 'Date',
          prop: 'date',
          component: 'el-input',
          add: true,
          edit: true,
          search: true,
          detail: true,
        },
        {
          label: 'Name',
          prop: 'name',
          component: 'el-input',
          add: true,
          search: true,
          detail: true,
        },
        {
          label: 'Address',
          prop: 'address',
          component: 'el-input',
          add: true,
          edit: true,
        },
      ])
    )
    const data = ref([
      {
        avatar: 'https://avatars.githubusercontent.com/u/23313167?v=4',
        date: '2016-05-03',
        name: 'qiang',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        avatar: 'https://avatars.githubusercontent.com/u/23313167?v=4',
        date: '2016-05-02',
        name: 'qiang',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      Refresh,
      form,
      columns,
      serachForm,
      data,
      currentPage,
      pageSize,
      total,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

<style scoped>
.list {
  margin-top: calc(var(--el-component-size) / 2);
}
.list .item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(var(--el-component-size) / 2) 0;
}
.list .item .item-content {
  display: flex;
}
.list .item .item-content .item-avatar {
  margin-right: var(--el-component-size);
  width: 100px;
  height: 100px;
  border-radius: 50%;
}

.item-info {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}
.item-info p {
  margin: 0;
  padding: 0;
}
.item-info .name {
  font-size: 22px;
  font-weight: bold;
}

.detail {
  display: flex;
  justify-content: center;
}
.detail .item-avatar {
  margin-right: 100px;
  width: 150px;
  height: 150px;
  border-radius: 50%;
}
</style>

Custom Dialog

The component defaults to using ElDialog as the dialog, you can customize the dialog through the crud-dialog slot

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="{ label: 'Operations' }"
    :data="data"
    :detail="detail"
    :column="1"
    :before-open="beforeOpen"
    selection
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  >
    <template #crud-dialog="{ type, props, createDescriptions, createForm }">
      <el-drawer v-bind="props">
        <component
          :is="type === 'detail' ? createDescriptions() : createForm()"
        />
      </el-drawer>
    </template>
  </pro-crud>
</template>

<script>
import { defineComponent, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import {
  defineCrudColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

export default defineComponent({
  setup() {
    const form = ref({})
    const serachForm = ref({})
    const detail = ref({})
    const columns = ref(
      defineCrudColumns([
        {
          label: 'Date',
          prop: 'date',
          component: 'el-input',
          add: true,
          edit: true,
          search: true,
          detail: true,
        },
        {
          label: 'Name',
          prop: 'name',
          component: 'el-input',
          add: true,
          search: true,
          detail: true,
        },
        {
          label: 'Address',
          prop: 'address',
          component: 'el-input',
          add: true,
          edit: true,
        },
      ])
    )
    const data = ref([
      {
        date: '2016-05-03',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
      {
        date: '2016-05-02',
        name: 'Tom',
        address: 'No. 189, Grove St, Los Angeles',
      },
    ])

    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      if (type === 'edit') {
        form.value = row || {}
      } else if (type === 'detail') {
        detail.value = row || {}
      }
      done()
    })

    const search = defineCrudSearch((done, isValid, invalidFields) => {
      ElMessage(`search: ${isValid}`)
      console.log('search', serachForm.value, isValid, invalidFields)
      setTimeout(() => {
        done()
      }, 1000)
    })

    const submit = defineCrudSubmit(
      (close, done, type, isValid, invalidFields) => {
        ElMessage(`submit: ${type}, ${isValid}`)
        console.log('submit', form.value, type, isValid, invalidFields)
        setTimeout(() => {
          isValid ? close() : done()
        }, 1000)
      }
    )

    const deleteRow = (row) => {
      ElMessage('deleteRow')
      console.log('deleteRow', row)
    }

    return {
      Refresh,
      form,
      columns,
      serachForm,
      data,
      detail,
      beforeOpen,
      search,
      submit,
      deleteRow,
    }
  },
})
</script>

<style>
.el-input__icon {
  width: 14px;
}
</style>

TypeScript

The function defineCrudColumns supports passing in a Generics type to infer the value of prop

<template>
  <pro-crud
    v-model="form"
    v-model:search="serachForm"
    :columns="columns"
    :menu="menu"
    :data="data"
    :detail="detail"
    :before-open="beforeOpen"
    label-width="100px"
    @search="search"
    @submit="submit"
    @delete="deleteRow"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  defineCrudColumns,
  defineCrudMenuColumns,
  defineCrudSubmit,
  defineCrudSearch,
  defineCrudBeforeOpen,
} from 'element-pro-components'

interface DataItem {
  date: string
  name: string
  address: string
}

const form = ref({})
const serachForm = ref({})
const detail = ref({})
const menu = defineCrudMenuColumns<DataItem>({
  label: 'Operations',
  edit: (row) => row.date !== '2016-05-02',
  del: (row) => row.date !== '2016-05-04',
  searchReset: false,
})
const columns = defineCrudColumns<DataItem>([
  {
    label: 'Date',
    prop: 'date',
    component: 'el-input',
    add: true,
    edit: true,
    search: true,
    detail: true,
  },
  {
    label: 'Name',
    prop: 'name',
    component: 'el-input',
    add: true,
    search: true,
    detail: true,
  },
  {
    label: 'Address',
    prop: 'address',
    component: 'el-input',
    add: true,
    edit: true,
    detail: true,
  },
])
const data = ref<DataItem[]>([
  {
    date: '2016-05-03',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-02',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
])

const beforeOpen = defineCrudBeforeOpen<DataItem>((done, type, row) => {
  if (type === 'edit') {
    form.value = row || {}
  } else if (type === 'detail') {
    detail.value = row || {}
  }
  done()
})

const search = defineCrudSearch((done, isValid, invalidFields) => {
  ElMessage(`search: ${isValid}`)
  console.log('search', serachForm.value, isValid, invalidFields)
  setTimeout(() => {
    done()
  }, 1000)
})

const submit = defineCrudSubmit((close, done, type, isValid, invalidFields) => {
  ElMessage(`submit: ${type}, ${isValid}`)
  console.log('submit', form.value, type, isValid, invalidFields)
  setTimeout(() => {
    isValid ? close() : done()
  }, 1000)
})

const deleteRow = (row: DataItem) => {
  ElMessage('deleteRow')
  console.log('deleteRow', row)
}
</script>

Props

NameDescriptionTypeOptionsDefault
v-modelbinding valueobject--
v-model:searchbinding search valueobject--
columnsto generate crud components, reference columnsarray--
add-columnsto generate add form components, reference Form columnsarray-from columns
edit-columnsto generate edit form components, reference Form columnsarray-from columns
form-columnsto generate form components, reference Form columnsarray-from columns
search-columnsto generate search components, reference Form columnsarray-from columns
table-columnsto generate table components, reference Table columnsarray-from columns
detail-columnsto generate detail components, reference Descriptions columnsarray-from columns
menuconfig the menu content, reference menuobject--
search-rulesvalidation rules of searchobject--
dataTable dataarray--
selectionadd a column will display checkbox, reference columnsboolean / object-false
indexadd a column will display index, reference columnsboolean / object-false
expandadd a column will display expand icon, reference columnsboolean / object-false
menuconfig the menu content, reference columnsboolean / object-false
show-overflow-tooltipwhether to hide extra content and show them in a tooltip when hovering on the cellboolean-false
alignalignmentstringleft / center / rightleft
header-alignalignment of the table header. If omitted, the value of the above align attribute will be appliedstringleft / center / rightsame with align
heightTable’s height. By default it has an auto height. If its value is a number, the height is measured in pixels; if its value is a string, the value will be assigned to element’s style.height, the height is affected by external stylesstring / number--
max-heightTable’s max-height. The legal value is a number or the height in px.string/number--
stripewhether Table is stripedboolean-false
borderwhether Table has vertical borderboolean-false
sizesize of Tablestringlarge / default /small-
fitwhether width of column automatically fits its containerboolean-true
show-headerwhether Table header is visibleboolean-true
highlight-current-rowwhether current row is highlightedboolean-false
current-row-keykey of current row, a set only propstring / number--
row-class-namefunction that returns custom class names for a row, or a string assigning class names for every rowFunction({row, rowIndex}) / string--
row-stylefunction that returns custom style for a row, or an object assigning custom style for every rowFunction({row, rowIndex}) / Object--
cell-class-namefunction that returns custom class names for a cell, or a string assigning class names for every cellFunction({row, column, rowIndex, columnIndex}) / string--
cell-stylefunction that returns custom style for a cell, or an object assigning custom style for every cellFunction({row, column, rowIndex, columnIndex}) / Object--
header-row-class-namefunction that returns custom class names for a row in table header, or a string assigning class names for every row in table headerFunction({row, rowIndex}) / string--
header-row-stylefunction that returns custom style for a row in table header, or an object assigning custom style for every row in table headerFunction({row, rowIndex}) / Object--
header-cell-class-namefunction that returns custom class names for a cell in table header, or a string assigning class names for every cell in table headerFunction({row, column, rowIndex, columnIndex}) / string--
header-cell-stylefunction that returns custom style for a cell in table header, or an object assigning custom style for every cell in table headerFunction({row, column, rowIndex, columnIndex}) / Object--
row-keykey of row data, used for optimizing rendering. Required if reserve-selection is on or display tree data. When its type is String, multi-level access is supported, e.g. user.info.id, but user.info[0].id is not supported, in which case Function should be used.Function(row) / string--
empty-textDisplayed text when data is empty. You can customize this area with #emptystring-No Data
default-expand-allwhether expand all rows by default, works when the table has a column type=“expand” or contains tree structure databoolean-false
expand-row-keysset expanded rows by this prop, prop’s value is the keys of expand rows, you should set row-key before using this propArray-
default-sortset the default sort column and order. property prop is used to set default sort column, property order is used to set default sort orderObjectorder: ascending, descendingif prop is set, and order is not set, then order is default to ascending
tooltip-effecttooltip effect propertystringdark / lightdark
show-summarywhether to display a summary rowboolean-false
sum-textdisplayed text for the first column of summary rowstring-Sum
summary-methodcustom summary methodFunction({ columns, data })--
span-methodmethod that returns rowspan and colspanFunction({ row, column, rowIndex, columnIndex })--
select-on-indeterminatecontrols the behavior of master checkbox in multi-select tables when only some rows are selected (but not all). If true, all rows will be selected, else deselected.boolean-true
indenthorizontal indentation of tree datanumber-16
lazywhether to lazy loading databoolean--
loadmethod for loading child row data, only works when lazy is trueFunction(row, treeNode, resolve)--
tree-propsconfiguration for rendering nested dataObject-{ hasChildren: ‘hasChildren’, children: ‘children’ }
table-layoutsets the algorithm used to lay out table cells, rows, and columnsstringfixed / autofixed
scrollbar-always-onalways show scrollbarbooleanfalse
flexibleensure main axis minimum-size doesn’t follow the contentbooleanfalse
v-model:current-pagecurrent page numbernumber--
v-model:page-sizeitem count of each pagenumber--
totaltotal item countnumber--
page-counttotal page count. Set either total or page-count and pages will be displayed; if you need page-sizes, total is requirednumber--
smallwhether to use small paginationboolean-false
backgroundwhether the buttons have a background colorboolean-false
default-page-sizedefault initial value of page sizenumber--
pager-countnumber of pagers. Pagination collapses when the total page count exceeds this valuenumberodd number between 5 and 217
default-current-pagedefault initial value of current-pagenumber--
layoutlayout of Pagination, elements separated with a commastringsizes / prev / pager / next / jumper / -> / total / slot‘prev, pager, next, jumper, ->, total’
page-sizesoptions of item count per pagenumber[]-[10, 20, 30, 40, 50, 100]
popper-classcustom class name for the page size Select’s dropdownstring--
prev-texttext for the prev buttonstring--
next-texttext for the next buttonstring--
disabledwhether Pagination is disabledboolean-false
hide-on-single-pagewhether to hide when there’s only one pageboolean--
rulesvalidation rules of formobject--
inlinewhether the form is inlineboolean-false
arraywhether the form is ArrayFormboolean-
maxlimit the maximum number of ArrayForm componentnumber--
label-positionposition of label. If set to ‘left’ or ‘right’, label-width prop is also requiredstringright / left / topright
label-widthwidth of label, e.g. ‘50px’. All its direct child form items will inherit this value. Width auto is supported.string--
label-suffixsuffix of the labelstring--
hide-required-asteriskwhether required fields should have a red asterisk (star) beside their labelsboolean-false
show-messagewhether to show the error messageboolean-true
inline-messagewhether to display the error message inline with the form itemboolean-false
status-iconwhether to display an icon indicating the validation resultboolean-false
validate-on-rule-changewhether to trigger validation when the rules prop is changedboolean-true
sizecontrol the size of components in this formstringlarge / default /small-
disabledwhether to disabled all components in this form. If set to true, it cannot be overridden by its inner components’ disabled propboolean-false
guttergrid spacingnumber-0
justifyhorizontal alignment of flex layoutstringstart / end / center / space-around / space-between / spacing-evenlystart
titletitle of Dialog. Can also be passed with a named slot (see the following table)string-reference addText or editText of menu
widthwidth of Dialogstring / number-50%
fullscreenwhether the Dialog takes up full screenboolean-false
topvalue for margin-top of Dialog CSSstring-15vh
modalwhether a mask is displayedboolean-true
append-to-bodywhether to append Dialog itself to body. A nested Dialog should have this attribute set to trueboolean-false
lock-scrollwhether scroll of body is disabled while Dialog is displayedboolean-true
open-delayTime(milliseconds) before opennumber-0
close-delayTime(milliseconds) before closenumber-0
close-on-click-modalwhether the Dialog can be closed by clicking the maskboolean-true
close-on-press-escapewhether the Dialog can be closed by pressing ESCboolean-true
show-closewhether to show a close buttonboolean-true
before-opencallback before Dialog opened, and it will prevent Dialog fromFunction(done, type, row)--
before-closecallback before Dialog closes, and it will prevent Dialog from closingFunction(done)--
centerwhether to align the header and footer in centerboolean-false
detaildetail data of displayobject--
borderwith or without borderboolean-false
columnnumbers of Descriptions Item in one linenumber-3
directiondirection of liststringvertical / horizontalhorizontal
sizesize of liststringlarge / default /small-
titletitle text, display on the top leftstring--
extraextra text, display on the top rightstring--
aligncolumn content alignment (If no border, effective for both label and content)stringleft / center / rightleft
label-aligncolumn label alignment, if omitted, the value of the above align attribute will be applied (If no border, please use align attribute)stringleft / center / right-

Tip

Crud supports all props of Table and Form. It also supports event props other than the title in the Descriptions, If you want to configure the title, please implement it through the descriptions-title slot. It also supports event props other than the modelValue destroy-on-close in the ElDialog, but it is not recommended to modify title and width.

In addition, some props have the same name, and the configuration will be passed to the required component.

columns

NameDescriptionTypeOptionsDefault
addwhether displayed in add formboolean-false
editwhether displayed in edit formboolean-false
formwhether displayed in formboolean-false
searchwhether displayed in searchboolean-false
detailwhether displayed in detailboolean-false
hidewhether hide in tableboolean-false
propthe key of datastring--
labelcolumn labelstring--
slotwhether to enable slotboolean-false
renderrender function for table columnsstring / Function(row)--
childrengrouping table headarray--
columnKeycolumn’s key. If you need to use the filter-change event, you need this attribute to identify which column is being filteredstring--
widthcolumn widthstring--
minWidthcolumn minimum width. Columns with width has a fixed width, while columns with min-width has a width that is distributed in proportionstring--
fixedwhether column is fixed at left/right. Will be fixed at left if truestring / booleantrue / left / right-
renderHeaderrender function for table header of this columnFunction(h, { column, $index })--
sortablewhether column can be sorted. Remote sorting can be done by setting this attribute to ‘custom’ and listening to the sort-change event of Tableboolean / stringtrue / false / ‘custom’false
sortMethodsorting method, works when sortable is true. Should return a number, just like Array.sortFunction(a, b)--
sortByspecify which property to sort by, works when sortable is true and sort-method is undefined. If set to an Array, the column will sequentially sort by the next property if the previous one is equalstring / array / Function(row, index)--
sortOrdersthe order of the sorting strategies used when sorting the data, works when sortable is true. Accepts an array, as the user clicks on the header, the column is sorted in order of the elements in the arrayarraythe elements in the array need to be one of the following: ascending, descending and null (restores to the original order)[‘ascending’, ‘descending’, null]
resizablewhether column width can be resized, works when border of el-table is trueboolean-true
formatterfunction that formats cell contentFunction(row, column, cellValue, index)--
showOverflowTooltipwhether to hide extra content and show them in a tooltip when hovering on the cellboolean-false
alignalignmentstringleft / center / rightleft
headerAlignalignment of the table header. If omitted, the value of the above align attribute will be appliedstringleft / center / rightsame with align
classNameclass name of cells in the columnstring--
labelClassNameclass name of the label of this columnstring--
filtersan array of data filtering options. For each element in this array, text and value are requiredArray[{ text, value }]--
filterPlacementplacement for the filter dropdownstringtop / top-start / top-end / bottom / bottom-start / bottom-end / left / left-start / left-end / right / right-start / right-end-
filterMultiplewhether data filtering supports multiple optionsboolean-true
filterMethoddata filtering method. If filter-multiple is on, this method will be called multiple times for each row, and a row will display if one of the calls returns trueFunction(value, row, column)--
filteredValuefilter value for selected data, might be useful when table header is rendered with render-headerarray--
indexcustomize indices for each row, works on columns with type=indexFunction(index) / number--
selectablefunction that determines if a certain row can be selected, works when type is ‘selection’Function(row, index)--
reserveSelectionwhether to reserve selection after data refreshing, works when type is ‘selection’. Note that row-key is required for this to workboolean-false
typetype of children internal formsstringarray / group / tabs / collapse / stepsarray
maxlimit the maximum number of sub-columnsnumber--
showwhether to show the current componentboolean-true
labelWidthwidth of label, e.g. ‘50px’. Width auto is supported.string--
requiredwhether the field is required or not, will be determined by validation rules if omittedboolean-false
rulesvalidation rules of formobject--
errorfield error message, set its value and the field will validate error and show this message immediatelystring--
showMessagewhether to show the error messageboolean-true
inlineMessageinline style validate messageboolean-false
sizecontrol the size of components in this form-itemstringlarge / default /small-
spannumber of column the grid spansnumber-24
offsetnumber of spacing on the left side of the gridnumber-0
pushnumber of columns that grid moves to the rightnumber-0
pullnumber of columns that grid moves to the leftnumber-0
xs<768px Responsive columns or column props objectnumber / object (e.g. {span: 4, offset: 4})--
sm≥768px Responsive columns or column props objectnumber / object (e.g. {span: 4, offset: 4})--
md≥992px Responsive columns or column props objectnumber / object (e.g. {span: 4, offset: 4})--
lg≥1200px Responsive columns or column props objectnumber / object (e.g. {span: 4, offset: 4})--
xl≥1920px Responsive columns or column props objectnumber / object (e.g. {span: 4, offset: 4})--
disabledwhether Tab is disabled, work on type=tabs or type=collapsebooleanfalse
closablewhether Tab is closable, work on type=tabsbooleanfalse
lazywhether Tab is lazily rendered, work on type=tabsbooleanfalse
descriptionstep description, work on type=stepsstring
iconstep custom icon, work on type=stepsstring / Component
statuscurrent status, work on type=stepsstringwait / process / finish / error / success
detailSpancolspan of descriptions columnnumber-1
widthdescriptions column width, the width of the same column in different rows is set by the max value (If no border, width contains label and content)string / number--
minWidthdescriptions column minimum width, columns with width has a fixed width, while columns with min-width has a width that is distributed in proportion (If noborder, width contains label and content)string / number--
aligndescriptions column content alignment (If no border, effective for both label and content)stringleft / center / rightleft
labelAligndescriptions column label alignment, if omitted, the value of the above align attribute will be applied (If no border, please use align attribute)stringleft / center / right-
classNamedescriptions column content custom class namestring--
labelClassNamedescriptions column label custom class namestring--
renderrender function for descriptions columnsFunction(detail)--
renderLabelrender function for LabelFunction(column)--

Tip

Crud columns supports all props of Table columns Form columns. It also supports event props other than the span in the Descriptions columns, The span needs to be rewritten as detailSpan to use

In addition, some props have the same name, and the configuration will be passed to the required component.

NameDescriptionTypeDefault
addwhether to display a add buttonbooleantrue
addTextthe text of add buttonstringAdd
addPropsthe props of add button, reference el-buttonobject{ type: ‘primary’ }
editwhether to display a edit buttonboolean / Function(row)true
editTextthe text of edit buttonstringEdit
editPropsthe props of edit button, reference el-buttonobject{ link: true, type: ‘primary’ }
detailwhether to display a detail buttonboolean / Function(row)true
detailTextthe text of detail buttonstringView
detailPropsthe props of detail button, reference el-buttonobject{ link: true, type: ‘info’ }
delwhether to display a del buttonboolean / Function(row)true
delTextthe text of del buttonstringDelete
delPropsthe props of del button, reference el-buttonobject{ link: true, type: ‘danger’ }
submitwhether to display a submit buttonbooleantrue
submitTextthe text of submit buttonstringSubmit
submitPropsthe props of submit buttonbutton, reference el-buttonobject{ type: ‘primary’ }
resetWhether to display a reset buttonbooleantrue
resetTextthe text of reset buttonstringReset
resetPropsthe props of reset buttonbutton, reference el-buttonobject-
prevTextthe text of prev buttonstringPrev
prevPropsthe props of prev button, reference el-buttonobject-
nextTextthe text of next buttonstringNext
nextPropsthe props of next button, reference el-buttonobject-
searchwhether to display a search buttonbooleantrue
searchTextthe text of search buttonstringSearch
searchPropsthe props of search , reference el-buttonobject{ type: ‘primary’ }
searchResetwhether to display a reset buttonbooleantrue
searchResetTextthe text of reset buttonstringReset
searchResetPropsthe props of reset button, reference el-buttonobject-
searchPrevTextthe text of prev buttonstringPrev
searchPrevPropsthe props of prev button, reference el-buttonobject-
searchNextTextthe text of next buttonstringNext
searchNextPropsthe props of next button, reference el-buttonobject-

Tip

Other attributes are the same as Table columns

Events

NameDescriptionParameters
submittriggers when the submit clickclose, done, ‘add’/‘edit’, isValid, invalidFields
resettriggers when the reset click-
add-itemtriggers when the add click in the formindexes: number[]
remove-itemtriggers when the remove click in the formindexes: number[]
collapse-changetriggers when the collapse change in the formactive: CollapseModelValue
tab-changetriggers when the tab change in the formname: TabPaneName
step-changetriggers when the step change in the formactive: string | number
addtriggers when the add click-
edittriggers when the edit clickrow
detailtriggers when the detail clickrow
deletetriggers when the delete clickrow
searchtriggers when the search clickdone, isValid, invalidFields
searchResettriggers when the search reset click-
add-itemtriggers when the add click in the search formindexes: number[]
remove-itemtriggers when the remove click in the search formindexes: number[]
collapse-changetriggers when the collapse change in the search formactive: CollapseModelValue
tab-changetriggers when the tab change in the search formname: TabPaneName
step-changetriggers when the step change in the search formactive: string | number
selecttriggers when user clicks the checkbox in a rowselection, row
select-alltriggers when user clicks the checkbox in table headerselection
selection-changetriggers when selection changesselection
cell-mouse-entertriggers when hovering into a cellrow, column, cell, event
cell-mouse-leavetriggers when hovering out of a cellrow, column, cell, event
cell-clicktriggers when clicking a cellrow, column, cell, event
cell-dblclicktriggers when double clicking a cellrow, column, cell, event
row-clicktriggers when clicking a rowrow, column, event
row-contextmenutriggers when user right clicks on a rowrow, column, event
row-dblclicktriggers when double clicking a rowrow, column, event
header-clicktriggers when clicking a column headercolumn, event
header-contextmenutriggers when user right clicks on a column headercolumn, event
sort-changetriggers when Table’s sorting changes{ column, prop, order }
filter-changecolumn’s key. If you need to use the filter-change event, this attribute is mandatory to identify which column is being filteredfilters
current-changetriggers when current row changescurrentRow, oldCurrentRow
header-dragendtriggers after changing a column’s width by dragging the column header’s bordernewWidth, oldWidth, column, event
expand-changetriggers when user expands or collapses a row (for expandable table, second param is expandedRows; for tree Table, second param is expanded)row, (expandedRows | expanded)
validatetriggers after a form item is validatedprop name of the form item being validated, whether validation is passed and the error message if not

Methods

NameDescriptionParameters
clearSelectionused in multiple selection Table, clear user selection-
toggleRowSelectionused in multiple selection Table, toggle if a certain row is selected. With the second parameter, you can directly set if this row is selectedrow, selected
toggleAllSelectionused in multiple selection Table, toggle select all and deselect all-
toggleRowExpansionused in expandable Table or tree Table, toggle if a certain row is expanded. With the second parameter, you can directly set if this row is expanded or collapsedrow, expanded
setCurrentRowused in single selection Table, set a certain row selected. If called without any parameter, it will clear selection.row
clearSortclear sorting, restore data to the original order-
clearFilterclear filters of the columns whose columnKey are passed in. If no params, clear all filterscolumnKeys
doLayoutrefresh the layout of Table. When the visibility of Table changes, you may need to call this method to get a correct layout-
sortsort Table manually. Property prop is used to set sort column, property order is used to set sort orderprop: string, order: string
validatevalidate the whole form. Takes a callback as a param. After validation, the callback will be executed with two params: a boolean indicating if the validation has passed, and an object containing all fields that fail the validation. Returns a promise if callback is omittedFunction(callback: Function(boolean, object))
validateFieldvalidate one or several form itemsFunction(props: string | array, callback: Function(errorMessage: string))
resetFieldsreset all the fields and remove validation result-
scrollToFieldScroll to the specified form fieldFunction(prop: string)
clearValidateclear validation message for certain fields. The parameter is prop name or an array of prop names of the form items whose validation messages will be removed. When omitted, all fields’ validation messages will be clearedFunction(props: string | array)
openDialogopen dialogFunction(type: ICrudDialogType, row?: UnknownObject)
closeDialogclose dialog-

Slots

NameDescriptionType
crud-tablecustom Table content{ props, size, columns, menu, showMenu, createTableMenu }
crud-dialogcustom dialog{ props, type, createForm, createDescriptions }
crud-searchcustom search content{ props, columns, menu }
crud-formcustom form content{ props, columns, menu }
crud-detailcustom detail content{ props, columns, size }
menu-leftcontrol the menu left display content{ size }
menu-rightcontrol the menu right display content{ size }
actioncontrol the menu right of the menu display content{ size }
menucontrol the menu display content of table{ size, row, column, $index }
dialog-topcontrol the top display content of dialog{ type }
dialog-bottomcontrol the bottom display content of dialog{ type }
tableanything inserted before the menu of table-
table-expandcontrol the expand display content, parameters{ row, column, $index }
table-appendContents to be inserted after the last row-
table-[prop]control the Item display content of table{ row, column, $index }
table-[prop]-headercontrol the Item header display content of table{ column, $index }
formanything inserted before the menu of form-
form-menu-leftcontrol the menu left display content of form{ loading: boolean }
form-menu-rightcontrol the menu right display content of form{ loading: boolean }
form-[prop]control the Item display content of form{ item: object, indexes?: number[], value: any, setValue: (value: any) => void }
form-[prop]-labelcontrol the Item label display content of form{ item: object, indexes?: number[] }
form-[prop]-errorcontrol the Item error display content of form{ error, item: object, indexes?: number[] }
searchanything inserted before the menu of search-
search-menu-leftcontrol the menu left display content of search{ loading: boolean }
search-menu-rightcontrol the menu right display content of search{ loading: boolean }
search-[prop]control the Item display content of search{ item: object, indexes?: number[], value: any, setValue: (value: any) => void }
search-[prop]-labelcontrol the Item label display content of search{ item: object, indexes?: number[] }
search-[prop]-errorcontrol the Item error display content of search{ error, item: object, indexes?: number[] }
detailanything inserted after the menu of descriptions-
detail-titlecustom title, display on the top left{ size }
detail-extracustom extra area, display on the top right{ size }
detail-[prop]control the Item display content{ size, item }
detail-[prop]-labelcontrol the Item label display content{ size, item }

Tip

[prop] the prop of columns