Element Pro Components

website·Indexed 29 days ago

https://tolking.github.io/element-pro-components/

A Vue 3 component library based on Element Plus that provides high-level business components. It features configuration-driven components such as Crud, ProForm, Table, and Search, as well as layout utilities, ColumnSetting for table visibility, and automatic breadcrumb and tab generation based on vue-router.

Tokens
57.8K
Snippets
309
Records
368
Agent score
73%

What's inside Element Pro Components

  1. Overview of element-pro-components

    element-pro-components is a component library for Vue 3 built upon element-plus, vue, and vue-router. It is designed to encapsulate non-business logic for common UI patterns like forms and tables, allowing developers to define table columns or form items via a column attribute (passed as an array) rather than writing repetitive template code. This approach enables dynamic UI updates and easier implementation of permission-based visibility by modifying the reactive column data.
  2. Overview of element-pro-components

    element-pro-components is a component library designed for mid-to-back-end development. It is built on top of element-plus, Vue 3, and vue-router. Its primary goal is to reduce boilerplate code in admin pages by encapsulating non-business logic into reusable components. Specifically, it allows developers to replace repetitive el-table-column and el-form-item declarations with a dynamic column configuration array. Because these configurations can be reactive, the resulting tables or forms will update automatically when the configuration changes, facilitating the implementation of features like permission-based UI control.
  3. Use TypeScript for type-safe table columns

    The defineTableColumns function supports a Generic type parameter. By passing an interface representing your data item, TypeScript can infer and validate the values assigned to the prop field, ensuring they match the keys of your data object.
    import { defineTableColumns, defineTableMenuColumns } from 'element-pro-components'
    
    interface DataItem {
      date: string
      name: string
      address: string
    }
    
    // The Generic <DataItem> ensures 'prop' values are keys of DataItem
    const columns = defineTableColumns<DataItem>([
      {
        label: 'Date',
        prop: 'date', // Type-checked
      },
      {
        label: 'Name',
        prop: 'name', // Type-checked
      },
    ])
    
    const menu = defineTableMenuColumns({
      label: 'Operations',
      align: 'center',
    })
    
  4. Retrieve nested values in pro-table columns

    The pro-table component supports retrieving values from nested objects or arrays by specifying a path in the prop configuration. For example, b.c accesses a nested object property, and d[0].e accesses a property within an array element.
    const columns = defineTableColumns([
      { label: 'Break', prop: 'b.c' },      // Nested object
      { label: 'Object', prop: 'b.d' },     // Nested object
      { label: 'Array', prop: 'd[0].e' },   // Nested array element
    ])
    
    const data = [
      {
        b: { c: 'value 1', d: 'value 2' },
        d: [{ e: 'value 3' }],
      },
    ]
  5. Handle external URLs and custom routing logic

    Starting from version 1.2.0, the Menu does not natively support full URL jumps. To handle external links, set :router="false" and use the @select event to manually handle navigation using a utility like isURL.
    <template>
      <pro-menu
        :routes="routes"
        :router="false"
        mode="horizontal"
        @select="handleSelect"
      />
    </template>
    
    <script>
    import { defineComponent } from 'vue'
    import { useRouter } from 'vue-router'
    import { isURL } from 'element-pro-components'
    
    export default defineComponent({
      setup() {
        const router = useRouter()
        const routes = [
          { path: '/internal', meta: { title: 'Internal' } },
          { path: 'https://github.com', meta: { title: 'Github' } },
        ]
    
        function handleSelect(value) {
          isURL(value) ? window.open(value) : router.push(value)
        }
    
        return { routes, handleSelect }
      },
    })
    
  6. Enable IntelliSense for description columns

    Use the defineDescriptionsColumns helper function from element-pro-components when defining your columns array to provide better IDE intelligence and type hinting.
    import { defineDescriptionsColumns } from 'element-pro-components'
    
    const columns = defineDescriptionsColumns([
      { label: 'Date', prop: 'date' },
      { label: 'Name', prop: 'name' },
      { label: 'Address', prop: 'address' },
    ])
  7. Disable specific Radio options

    To make a specific radio option unavailable, add disabled: true to the corresponding object within the data array passed to the pro-radio component.
    const list = ref([
      { value: 'Go', label: 'go', disabled: true }, // This option will be disabled
      { value: 'JavaScript', label: 'javascript' },
    ])
  8. Implement column visibility and ordering with ColumnSetting

    The pro-column-setting component is used to manage the display and sequence of columns in a table. It uses v-model to bind to a columns array. Users can toggle column visibility via checkboxes and change the column order by dragging the items. It supports nested column structures (multi-level headers) using the children property in the column definition.
    <template>
      <pro-column-setting
        v-model="columns"
        default-expand-all
        style="float: right; margin-bottom: 10px"
      />
      <pro-table :data="data" :columns="columns" />
    </template>
    
    <script>
    import { defineComponent, ref } from 'vue'
    
    export default defineComponent({
      setup() {
        const columns = ref([
          {
            label: 'Date',
            prop: 'date',
          },
          {
            label: 'User',
            prop: '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',
          },
          // ... more data
        ])
    
        return { data, columns }
      },
    })
    </script>
  9. Bind ProForm fields to nested object keys

    ProForm supports nested object and array assignment directly through the prop configuration. Use dot notation for objects (e.g., a.b.c) and bracket notation for arrays (e.g., b[0]). Note: If a prop has a default value, nested assignment will be blocked.
    const form = ref({ 'a.b': undefined })
    const columns = defineFormColumns([
      {
        label: 'Break',
        prop: 'a.b',
        component: 'el-input',
      },
      {
        label: 'Object',
        prop: 'a.b.c',
        component: 'el-input',
      },
      {
        label: 'Array',
        prop: 'b[0]',
        component: 'el-input',
      },
    ])
    
  10. Use Intellisense helpers for Crud definitions

    To improve developer experience and type safety when defining Crud components, use the provided helper functions from element-pro-components. These wrappers ensure that the columns and handler functions follow the expected schema.
    import {
      defineCrudColumns,
      defineCrudSubmit,
      defineCrudSearch,
      defineCrudBeforeOpen,
    } from 'element-pro-components'
    
    // Typed columns definition
    const columns = defineCrudColumns([
      { label: 'Name', prop: 'name', component: 'el-input', add: true }
    ])
    
    // Typed beforeOpen handler
    const beforeOpen = defineCrudBeforeOpen((done, type, row) => {
      done()
    })
    
    // Typed search handler
    const search = defineCrudSearch((done, isValid, invalidFields) => {
      done()
    })
    
    // Typed submit handler
    const submit = defineCrudSubmit((close, done, type, isValid, invalidFields) => {
      isValid ? close() : done()
    })