cruda

A CRUD viewmodal, provides unified APIs for different UIFrameworks
1,140 7
Install
npm install cruda
Latest Version:1.20.1
License:MIT
Last Updated:Aug 13, 2026
Links: GitHub  ·  npm
Maintainer: holyhigh

Cruda Cruda

npm NPM

A CRUD view model provides hosting of data, states and operations like submit()/form.name/loading.table, which makes developers build CRUD view faster.

Cruda provides unified APIs for different UIFrameworks by Cruda-adapters.

Conception

Cruda

Demos

Features

  • Data hosting
<!-- $crud.query (query data hosting) -->
<el-input v-model="$crud.query.xxx"></el-input>
<!-- $crud.table.data (table data hosting) -->
<el-table v-model="$crud.table.data"></el-table>
<!-- $crud.form (form data hosting) -->
<el-form :model="$crud.form"></el-form>
<!-- $crud.table.data (tree data hosting) -->
<el-tree :model="$crud.table.data"></el-tree>
  • Operation hosting
$crud.submit(formEl) //submit form
$crud.reload() //reload table 
$crud.cancel() //cancel form
  • State hosting
<!-- loading.query will be set automatically when reload() is called -->
<button class="..." :loading="$crud.loading.query" @click="$crud.reload()">
  查询
</button>
  • Logical encapsulation
/* when you call the toQuery(), Cruda will
1. set loading.query to True
2. package query, pagination, order, ...
3. emit hooks
4. catch exceptions
5. ...
*/
$crud.toQuery()
  • RESTful HTTP Method
$crud.toQuery() //GET
$crud.toDelete() //DELETE
$crud.doUpdate() //PUT
  • UIFrameworks supports
  • Multi-instance supports
  • ...

Usage

1. Install

2. Activate

3. Multi-instance

4. Hooks

5. Custom component

6. URL params

7. Global defaults

You can set global defaults of Cruda if all scenes have the same behavior in your project.

//what properties does 'rs' have depends on the backend return value
CRUD.defaults[CRUD.HOOK.AFTER_QUERY] = function (crud, rs) {
  crud.pagination.total = rs.data.total
  crud.table.data = rs.data.records || []
}
CRUD.defaults.pagination.pageSize = 10
CRUD.defaults.view.opQuery = true
CRUD.defaults.table.rowKey = 'id'

8. RESTAPI

You can modify the URL/Method to adapt to the backend service

CRUD.RESTAPI = {
  QUERY: { url: "", method: "GET" },
  QUERY_DETAILS: { url: "/{id}", method: "GET" },//(v1.20+)
  ADD: { url: "", method: "POST" },
  UPDATE: { url: "", method: "PUT" },
  DELETE: { url: "", method: "DELETE" },
  EXPORT: { url: "/export", method: "GET" },
  IMPORT: { url: "/import", method: "POST" },
  SORT: { url: "/sort", method: "PUT" },
  COPY: { url: "/copy", method: "POST" },
  ADD_OR_UPDATE: { url: "/addorupdate", method: "POST" },//(v1.20+)
}
Instance API (v1.9+)

Or set instance-only API when Activation

const $crud = useCrud({
  url:'/api/single',
  restApi:{
    //支持对象格式或字符串格式(仅能设置url)
    ADD:{url:'/add-batch',method:'POST'},
    COPY:'/copy2'
  }
})

* Note the api key must be uppercase

9. xApi (v1.5+)

CRUD.xApi(apiName, apiUrl, config) is used to extend custom CRUD RESTAPI. Below is an example

//1. Extends an API. After that it will
/**
 * a. Attach a method 'toClone' to the CRUD instance
 * b. Add 'BEFORE_CLONE' and 'AFTER_CLONE' to CRUD.HOOK
 */
CRUD.xApi('clone','/clone',{method:'POST'})
//2. Add listener
onHook(this,CRUD.HOOK.AFTER_CLONE,(crud,rs)=>{
  console.log('xApi-->',rs.data)
})
//3. Call toClone
this.$crud.toClone({x:1,y:2});

10. Auto Response (v1.8+)

We can config autoResponse to refresh the table view automatically, this could help you to avoid losing the page state if you reload() the page after add/update/delete/copy submition before. A typical case is you may lose all hierarchies of TreeTable you opened before when you reload(). Below is the config

//1. Set a response validator to check if the response is valid
$crud.autoResponse.validator = (response:{status:number})=>{
  return response.status === 200
}
//2. For such an Add-Oper like add/copy/import/..., it must set a getter in order to obtain new records with primary key from backend
CRUD.defaults.autoResponse.getter = (response:any)=>{
  return [response.data]
}
//2. If primary keys are generated at frontend, you can either return submitRows
CRUD.defaults.autoResponse.getter = (response:any,submitRows?:any[])=>{
  return submitRows
}
//3. For TreeTable, you need set parentKeyField in order to find parentNode. Default 'pid'
CRUD.defaults.autoResponse.parentKeyField = 'pid'
//4. Set insert position with 'head/tail'. Default 'head'
CRUD.defaults.autoResponse.position = 'head'
//4. For TreeTable, you need set childrenKeyField in order to find childNodes. Default 'children'
CRUD.defaults.autoResponse.childrenKeyField = 'children'

After that, the table view will refreshed by CRUDA. If you want to refresh manually you can call autoProcess() in the hook below

// Other hooks which can invode autoProcess please see the doc below 
onHook(CRUD.HOOK.AFTER_DELETE,(crud,rs,rows,autoProcess)=>{
  autoProcess()
})

11. Frontend Pagination (v1.11+)

We can config pagination.frontend to enable the frontend pagination

useCrud({
  ...
  pagination:{
    //enable
    frontend:true,
  }
})
//Set global cache hook(Optional)
CRUD.defaults[CRUD.HOOK.BEFORE_CACHE] = function (crud, rs, cache) {
  //cache custom data
  cache({
    data:{
      rows:rs.data.rows,
      total:rs.data.total
    }
  })
}
CRUD.defaults[CRUD.HOOK.AFTER_QUERY] = function (crud, rs, params, slice) {
  //filter cache data
  const keyword = params.keyword
  let list = filter(defaultTo(rs.data.rows, []),(item:any)=>{
    return test(item.email, keyword) ||
    test(item.uname, keyword) ||
    test(item.ip, keyword) ||
    test(item.domain, keyword)
  })
  crud.pagination.total = defaultTo(list.length, 0);
  //use slice() to slice list. If pagination.frontend is disabled, slice() will return the list directly 
  crud.table.data = slice(list);
}

After enabling pagination.frontend the method toQuery/reload no longer requests the backend, use reset instead

Cruda API

Props

  • view ✅⚡

    Display switch of Components

    • opQuery
    • opAdd
    • opUpdate
    • opDelete
    • opExport
    • opImport
    • opSort
    • opCopy
  • loading

    Toggle loading state

    • query
    • table
    • del
    • submit
    • form
    • export
    • import
    • sort
    • copy
  • query

    Query data container

  • sortation

    Sort data container

  • table

    Table data container

    • data
    • selection
    • allColumns
    • orders
    • rowKey✅
  • pagination⚡

    Pagination container

    • pageSize✅
    • currentPage
    • total
    • frontend
  • form

    Form data container

  • formStatus

    form state. 0:Normal;1:Add;2:Update;3:View;4:AddOrUpdate

  • params

    crud active params

  • error

    crud error msg{name,message,status}

  • editingId

    editing id of the table.row

  • key

    crud key in multi-instance

  • recoverable✅⚡

    enable/disable editing snapshot

  • snapshots

    snapshot map. The key is table.row[rowKey]

  • invalidBreak✅⚡

    will break the validation after first catch

  • autoResponse✅⚡

    will update table view automatically after you add/update/delete/copy crud.table.data

  • defaultQuery⚡

    Will merge into the GET request

  • restApi⚡

    Instance api that will recover the 8. RESTAPI

  • cache⚡

    Enable query cache and custom cache data by hook BEFORE_CACHE or use default backend response as the cache data. This prop will be true if pagination.frontend is enabled.

✅ Indicates that global defaults are supported ⚡ Indicates that activation in object form is supported

Methods

  • toQuery(query?: Record<string, any>) : Promise

    (When frontend is false) Instance query. Send GET request to the backend。The argument 'query' will merge with the $crud.query

  • toDelete(rows: Record<string, unknown> | Record<string, unknown>[]) : Promise

    Instance del. Send DELETE request to the backend

  • toExport() : Promise

    Instance export. Send GET request to the backend

  • toImport(file: File | File[],fieldName) : Promise

    Instance import. Use fieldName to specify the fileName of server request。 Send POST request to the backend

  • toAdd(...args)

    Set formStatus to 'Add'

  • toUpdate(row) : Promise

    Set formStatus to 'Update' and send GET (default) request to the backend

  • toAddOrUpdate(...args) : Promise

    Set formStatus to 'AddOrUpdate' and send GET (default) request to the backend

  • toView(row?: Record<string, any>) : Promise

    Set formStatus to 'View' and send GET (default) request to the backend

  • toSort() : Promise

    Instance sort. Send PUT (default) request to the backend

  • toCopy() : Promise

    Instance copy. Send POST (default) request to the backend

  • cancel()

    Set formStatus to 'Normal'

  • submit(...args) : Promise

    Pass args to BEFORE_SUBMIT

  • submitAdd(...args) : Promise

    Same as submit() but won't check formStatus

  • submitUpdate(...args) : Promise

    Same as submit() but won't checkformStatus

  • submitAddOrUpdate(...args) : Promise

    Same as submit() but won't checkformStatus

  • submitForm(form, ...args)

    *Depends on adapters。Will validate one or more Form or CustomComponent(which has validate() method) and then call submit()

  • reload(query?: Record<string, any>) : Promise

    Reset pagination and call toQuery()

  • getRestURL() : string

    Return restUrl of instance

  • setURLParams(paramObj)

    Set url params

  • getDetails(rowId) : Promise

    Return row data

  • changeSelection(selection: Record<string, any>[])

    Usually used in row selection event like selection-change in element-ui

  • changeOrder(sortData: { column: Record<string, any> prop: string order: string | null })

    Usually used in table sort event like sort-change in element-ui, it will call toQuery() automatically

  • getContext()

    Return the context of the crud

  • reset(query?: Record<string, any>) : Promise

    Clear cache data and call reload()

Hooks

  • BEFORE_QUERY(crud,params,orders,cancel) async

    Emit before query. Can modify the params before request send. Cancellable, if be cancelled the AFTER_QUERY will not emit

  • AFTER_QUERY(crud,rs,params,slice) async

    Emit after query. Can set table data by 'rs'. If pagination.frontend is enabled, params and slice() can be used to filter and slice cache data

  • BEFORE_DELETE(crud,rows,cancel) async

    Emit before delete. Cancellable, if be cancelled the AFTER_DELETE will not emit

  • AFTER_DELETE(crud,rs,rows,autoProcess) async

    Emit after delete. Use autoProcess() to update table view

  • BEFORE_ADD(crud,cancel,...args) async

    Emit before add. Can clear the form data or generate a UUID. Cancellable,if be cancelled the formStatus will not be change. ...args from toAdd()

  • AFTER_ADD(crud,rs,autoProcess) async

    Emit after add and before AFTER_SUBMIT. Use autoProcess() to update table view

  • BEFORE_UPDATE(crud,row,cancel,skip) async

    Emit before update. Cancellable,if be cancelled the formStatus will not be change. Use skip() to stop detail-query and the AFTER_DETAILS will not emit

  • AFTER_UPDATE(crud,rs,autoProcess) async

    Emit after update and before AFTER_SUBMIT. Use autoProcess() to update table view

  • BEFORE_ADD_OR_UPDATE(crud,cancel,doView,...args) async

    Emit before add/update. Cancellable,if be cancelled the formStatus will not be change. Use doView() to query details

  • AFTER_ADD_OR_UPDATE(crud,rs,autoProcess) async

    Emit after add/update and before AFTER_SUBMIT. Use autoProcess() to update table view

  • BEFORE_VIEW(crud,row,params,cancel,skip) async

    Emit before view. Cancellable,if be cancelled the formStatus will not be change. Use skip() to stop detail-query and the AFTER_DETAILS will not emit

  • AFTER_DETAILS(crud,rs) async

    Emit after toUpdate/toView and is not skipped by skip()

  • AFTER_DETAILS_UPDATE(crud,rs) async

    Emit after toUpdate and AFTER_DETAILS

  • AFTER_DETAILS_VIEW(crud,rs) async

    Emit after toView and AFTER_DETAILS

  • BEFORE_SUBMIT(crud,cancel,setForm,...args) async

    Emit before form submit. Cancellable, if be cancelled the AFTER_SUBMIT will not emit. Use setForm(formObject) to set form-data to submit

  • AFTER_SUBMIT(crud,rs,autoProcess) async

    Emit after form submit. Can reload page, send notice here. Use autoProcess() to update table view

  • BEFORE_EXPORT(crud,params,orders,cancel) async

    Emit before export. Cancellable, if be cancelled the AFTER_EXPORT will not emit

  • AFTER_EXPORT(crud,rs) async

    Emit after export complete

  • BEFORE_IMPORT(crud,params,file,cancel) async

    Emit before import. Can modify the params before request send. Cancellable, if be cancelled the AFTER_IMPORT will not emit

  • AFTER_IMPORT(crud,rs) async

    Emit after import complete

  • BEFORE_SORT(crud,sortation,cancel) async

    Emit before sort. Cancellable, if be cancelled the AFTER_SORT will not emit

  • AFTER_SORT(crud,rs) async

    Emit after sort complete

  • BEFORE_COPY(crud,rows,cancel) async

    Emit before copy. Cancellable, if be cancelled the AFTER_COPY will not emit

  • AFTER_COPY(crud,rs,rows,autoProcess) async

    Emit after copy complete. Use autoProcess() to update table view

  • ON_ERROR(crud,error)

    Emit on error

  • ON_CANCEL(crud)

    Emit after cancel() be called

  • ON_VALIDATE(crud,isValid,invalidFields)

    Emit after submitForm() be called

  • BEFORE_RECOVER(crud,cancel,snapshot) async

    Emit before recover the snapshot

  • BEFORE_CACHE(crud,rs,cache) async

    Emit after query and cache is enabled. Use cache(data) to custom the cache data

Errors

  • Must specify 'crudName' when multiple instances detected

    Rx 【Custom component】

  • form validation Xxx

    Rx 【check validation rules】

  • Cannot find [request] in the installation options

    Rx 【Install】

  • table.rowKey is a blank value 'Xxx', it may cause an error - toDelete/Update/View()

    Rx 【set rowKey a non-empty value】

Workflow

Cruda Workflow

Related Packages

metaflow-js

EntityFramework for Metaflow

2,894 0
innerken-utils

Utils for innerken GmbH

1,880 0
xcrud

A simplified crud component based on element-ui & Vue

21,831 31

Version History

Version Released License
1.20.1 MIT
1.20.0 MIT
1.11.3 MIT
1.11.2 MIT
1.11.1 MIT