搭配基于fusion封装的GovTable使用。
tnpm i @aligov/components-use-form-table-hooks -S
下面是场景的列表查询的例子,由 form + table + 分页组成
import React from 'react';
import { Pagination } from '@alifd/next';
import { Field, FormButtonGroup, Reset, SchemaForm, Submit } from '@uform/next';
import GovTable from '@aligov/components-gov-table';
import useFormTableHooks from '@aligov/components-use-form-table-hooks';
async function getData(params) {
return await {
total: 1000,
list: [
{id: 1, content: 'a'},
{id: 2, content: 'b'}
]
};
}
function Page() {
const {
loading, // 是否为加载状态
data = {}, // 当前列表数据
search, // 表单搜索触发提交
reload, // 重新搜索,用于操作后更新列表场景
changeTable, // 表格翻页接口
} = useFormTableHooks(getData);
const columns = [
{
title: 'ID',
dataIndex: 'id',
},
{
title: 'Content',
dataIndex: 'content'
}
];
const { list, total = 0, current = 1, pageSize = 10 } = data;
return (
<div>
<SchemaForm
labelCol={6}
wrapperCol={18}
autoAddColon={false}
onSubmit={search}
>
<Field name="id" type="string"/>
<FormButtonGroup>
<Submit>查询</Submit>
<Reset>重置</Reset>
</FormButtonGroup>
</SchemaForm>
<GovTable loading={loading} dataSource={list} columns={columns} hasBorder={false} />
<Pagination
onChange={changeTable}
current={current}
total={total}
pageSize={pageSize}
/>
</div>
);
}
const hookExport = useFormTableHooks(searchService, options);
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
searchService | 必须,根据表单及分页参数来查询列表内容 | (any) => Promise |
|
options | 可选,定制处理 | Object | {} |
options.defaultPageSize | 表格每页条目数量 | Number | 10 |
options.initData | 用来给表单或其它查询相关参数设定默认值 | Object | {} |
options.waitUntilManualCall | 初始化后不自动查询,配合 hook 返回结果中的 readyToSearch 方法来使用,用于需要等待某些异步结果才能查询的场景 |
Boolean | false |
options.trim | 是否在发送请求时,对请求参数中字符串类型的值做 trim 处理(仅第一层) | Boolean | true |
options.initSort | 初始化的表格排序设置,详见 Fusion 中 Table 的 sort 属性 | Object | {} |
options.sortFormatter | 排序参数发送请求前的格式化方案,默认是把所有对象放到 sortParams key 中 |
(any) => any | sortParams => ({ sortParams: sortParams }) |
options.initFilterParams | 初始化时的表格过滤设置,详见 Fusion 中 Table 的 filterParams 属性 | Object | {} |
options.filterFormatter | 表格过滤参数发送请求前的格式化方案,默认是把所有对象放到 filterParams key 中 |
(any) => any | filterParams => ({ filterParams: filterParams }) |
返回结果是一个对象,包含以下属性
属性 | 说明 | 类型 |
---|---|---|
loading | 是否正在请求中 | Boolean |
formData | form 表单参数,包含了 options.initData 中的内容 |
Object |
data | 列表数据,主要是 searchService 的返回结果 |
any |
search | 触发表单查询,会重置页码为 1。可携带额外的参数来查询 | (extraParams?: object} => void |
reload | 刷新当前页,常用于表格操作后刷新的场景,可携带额外的参数来表示可能移除的数量,用于避免最后一页条目都不再展示后页码不对的场景 | (deleteCount: Number = 0) => void |
changeTable | 表格翻页,主要用于 Fusion Pagination 组件的 onChange 属性 | (current: number) => void |
readyToSearch | 调用后解除 options.waitUntilManualCall 的控制,触发表单查询及后续的响应 |
Function |
updateFormData | 更新表单数据,但不触发查询,不常用 | (data: Object) => void |
updateTableData | 直接更新列表数据,主要用于操作后不发送请求来完全刷新列表的场景,不常用 | (tableData: any) => void |
updateTableRow | 直接更新列表某行数据,不常用 | (index: number, rowData: any) => void |
sortParams | Table 的 sort 属性 | Object |
onSort | Table 的 onSort 属性 | (dataIndex: string, order: string) => void |
filterParams | Table 的 filterParams 属性 | Object |
onFilter | Table 的 onFilter 属性 | (filterParams: Object) => void |
默认情况下,在调用 hooks 时就会马上调用 searchService 来获取数据。但如果需要先获取某些异步数据(如表单某些地方需要通过异步来获取并设置默认值),那么可通过 options.waitUntilManualCall
以及返回的 readyToSearch
来搭配使用。
例子:
const { readyToSearch, updateFormData } = useFormTableHooks(searchService, { waitUntilManualCall: true });
asyncFn().then((res = {}) => {
updateFormData(res);
readyToSearch();
});
searchService
一般应该满足前后端接口规范中的[列表类接口][guide-ajax-list]的约定里的 data
格式(注意:后端接口本身应满足完全的结构,但经通用请求库包装后,service 只会返回接口里的有效数据 data
), 即假设是分页的场景。
但如果接口本身不满足通用的列表查询规范,而是直接返回一个数组。那么 hook 返回结果种的 data
将不是一个 object,而是数组。这个时候则需要根据实际的数据结构来展示。
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {Button, Message, Pagination} from '@alifd/next';
import {Field, FormButtonGroup, FormItemGrid, Reset, SchemaForm, Submit} from '@uform/next';
import UseFormTableHooks, {ISearchParams} from '@aligov/components-use-form-table-hooks';
import GovTable from '@aligov/components-gov-table';
const dataSource = {
total: 55,
list: [
{
name: '张三',
age: '12'
}, {
name: '李四',
age: '13'
}]
};
const getData = (params) => {
console.log('查询参数', params);
return new Promise((resolve, reject) => {
setTimeout(() => resolve(dataSource), 1000);
})
};
function App() {
const {
loading,
data = {},
formData = {},
search,
reload,
changeTable,
updateFormData,
} = UseFormTableHooks(getData, {
initData: {},
});
const {list, total, current, pageSize} = data;
const columns = [{
title: '姓名',
dataIndex: 'name'
}, {
title: '年龄',
dataIndex: 'age'
}];
return (
<div>
<SchemaForm
labelCol={6}
wrapperCol={18}
value={formData}
onChange={updateFormData}
onSubmit={search}
>
<FormItemGrid cols={[8, 8, 8]}>
<Field name="name" type="string" title="姓名"></Field>
<Field name="age" type="string" title="年龄"/>
</FormItemGrid>
<FormButtonGroup>
<Submit>查询</Submit><Reset>重置</Reset>
</FormButtonGroup>
</SchemaForm>
<GovTable loading={loading} hasBorder={false} dataSource={list} columns={columns}/>
<Pagination
onChange={changeTable}
current={current}
total={total}
pageSize={pageSize}
className={'pagination'}
/>
</div>
);
}
ReactDOM.render((
<App/>
), mountNode);
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {Button, Message, Pagination} from '@alifd/next';
import {Field, FormButtonGroup, FormItemGrid, Reset, SchemaForm, Submit} from '@uform/next';
import UseFormTableHooks, {ISearchParams} from '@aligov/components-use-form-table-hooks';
import GovTable from '@aligov/components-gov-table';
const dataSource = {
list: [],
init() {
for (let i = 0; i < 55; i++) {
this.list.push({
name: `name-${i}`,
age: Math.round(Math.random() * 50)
});
}
},
getPageData(current, pageSize) {
const start = (current - 1) * pageSize;
const end = start + pageSize;
const list = this.list.slice(start, end);
return {
current,
pageSize,
total: this.list.length,
list,
}
},
remove(count) {
this.list = this.list.slice(0, this.list.length - count);
},
reset() {
this.list = [];
this.init();
}
};
dataSource.init();
const getData = (params) => {
console.log('查询参数', params);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(dataSource.getPageData(params.current, params.pageSize));
}, Math.round(Math.random()*1000));
})
};
function App() {
const {
loading,
data = {},
formData = {},
search,
reload,
changeTable,
updateFormData,
updateTableData,
updateTableRow,
} = UseFormTableHooks(getData, {
initData: {},
});
const {list, total, current, pageSize} = data;
const columns = [{
title: '姓名',
dataIndex: 'name'
}, {
title: '年龄',
dataIndex: 'age'
}];
const handleDelete1Row = () => {
dataSource.remove(1);
reload(1);
};
const handleReset = () => {
dataSource.reset();
reload();
};
return (
<div>
<SchemaForm
labelCol={6}
wrapperCol={18}
value={formData}
onChange={updateFormData}
onSubmit={search}
>
<FormItemGrid cols={[8, 8, 8]}>
<Field name="name" type="string" title="姓名" />
<Field name="age" type="string" title="年龄"/>
</FormItemGrid>
<FormButtonGroup>
<Submit>查询</Submit><Reset>重置</Reset>
</FormButtonGroup>
</SchemaForm>
<div style={{ margin: '20px 0' }}>
<Button onClick={handleReset}>重置数据</Button>
<Button onClick={handleDelete1Row} style={{ marginLeft: 20 }}>删除一行</Button>
<Button onClick={reload} style={{ marginLeft: 20 }}>不减少数据的操作</Button>
</div>
<GovTable loading={loading} hasBorder={false} dataSource={list} columns={columns}/>
<Pagination
onChange={changeTable}
current={current}
total={total}
pageSize={pageSize}
className={'pagination'}
/>
</div>
);
}
ReactDOM.render((
<App/>
), mountNode);
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {Button, Message, Pagination} from '@alifd/next';
import {Field, FormButtonGroup, FormItemGrid, Reset, SchemaForm, Submit} from '@uform/next';
import UseFormTableHooks, {ISearchParams} from '@aligov/components-use-form-table-hooks';
import GovTable from '@aligov/components-gov-table';
const dataSource = {
current: 1,
total: 20,
pageSize: 15,
list: [
{name: '张三', age: '12'},
{name: '李四', age: '13'}
]
};
const getData = (params) => {
console.log('查询参数', params);
return new Promise((resolve, reject) => {
resolve(dataSource);
})
};
function App() {
const {
loading,
data = {},
formData = {},
search,
reload,
changeTable,
updateFormData,
updateTableData,
updateTableRow,
} = UseFormTableHooks(getData, {
initData: {},
});
const {list, total, current, pageSize} = data;
const columns = [{
title: '姓名',
dataIndex: 'name'
}, {
title: '年龄',
dataIndex: 'age'
}];
const handleUpdateTableData = () => {
const newList = [
{name: '刘一', age: '22'},
{name: '陈二', age: '33'}
];
updateTableData({
...data,
list: newList
});
};
const handleUpdateFirstRow = () => {
const newFirstRow = {name: '黄药师', age: '40'};
updateTableRow(0, newFirstRow);
};
return (
<div>
<SchemaForm
labelCol={6}
wrapperCol={18}
value={formData}
onChange={updateFormData}
onSubmit={search}
>
<FormItemGrid cols={[8, 8, 8]}>
<Field name="name" type="string" title="姓名"></Field>
<Field name="age" type="string" title="年龄"/>
</FormItemGrid>
<FormButtonGroup>
<Submit>查询</Submit><Reset>重置</Reset>
</FormButtonGroup>
</SchemaForm>
<div style={{ margin: '20px 0' }}>
<Button onClick={handleUpdateTableData}>更新表格数据</Button>
<Button onClick={handleUpdateFirstRow} style={{ marginLeft: 20 }}>更新第一行数据</Button>
</div>
<GovTable loading={loading} hasBorder={false} dataSource={list} columns={columns}/>
<Pagination
onChange={changeTable}
current={current}
total={total}
pageSize={pageSize}
className={'pagination'}
/>
</div>
);
}
ReactDOM.render((
<App/>
), mountNode);
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {Button, Message, Pagination} from '@alifd/next';
import {Field, FormButtonGroup, FormItemGrid, Reset, SchemaForm, Submit} from '@uform/next';
import UseFormTableHooks, {ISearchParams} from '@aligov/components-use-form-table-hooks';
import GovTable from '@aligov/components-gov-table';
const dataSource = {
total: 55,
list: [
{
name: '张三',
age: '12'
}, {
name: '李四',
age: '13'
}]
};
const nameFilters = [
{ label: '张三', value: '张三' },
{ label: '李四', value: '李四' },
]
const getData = (params) => {
console.log('查询参数', params);
return new Promise((resolve, reject) => {
setTimeout(() => resolve(dataSource), 1000);
})
};
function App() {
const {
loading,
data = {},
formData = {},
search,
reload,
changeTable,
updateFormData,
sortParams,
onSort,
filterParams,
onFilter,
} = UseFormTableHooks(getData, {
initData: {},
});
const {list, total, current, pageSize} = data;
const columns = [{
title: '姓名',
dataIndex: 'name',
filters: nameFilters,
}, {
title: '年龄',
dataIndex: 'age',
sortable: true,
}];
return (
<div>
<div>DEMO 中不对数据做实际的排序和过滤,打开 console 看查询参数</div>
<SchemaForm
labelCol={6}
wrapperCol={18}
value={formData}
onChange={updateFormData}
onSubmit={search}
>
<FormItemGrid cols={[8, 8, 8]}>
<Field name="name" type="string" title="姓名" />
<Field name="age" type="string" title="年龄"/>
</FormItemGrid>
<FormButtonGroup>
<Submit>查询</Submit><Reset>重置</Reset>
</FormButtonGroup>
</SchemaForm>
<GovTable
loading={loading}
hasBorder={false}
dataSource={list}
columns={columns}
sort={sortParams}
onSort={onSort}
filterParams={filterParams}
onFilter={onFilter}
/>
<Pagination
onChange={changeTable}
current={current}
total={total}
pageSize={pageSize}
className={'pagination'}
/>
</div>
);
}
ReactDOM.render((
<App/>
), mountNode);