亲子过滤器
遗产功能快照( Q)@akinon/ui/akifilter-old(中文(简体) )
- Schema 驱动的表格: 构建主过滤器 UI
filterSchema使用FormBuilderWatch,应用labelRightAligned道具和反映初始值useAppliedFilters[0]或坚持储存. - 环境管理状态数字 :
FilterContextProvider来源mainPath从路由器(或customMainPath),存储appliedFilters, (中文(简体) ),applicableFilters,以及shownFilters通过useImmerReducer,并披露更新动作. - 本地存储持久性: 阅读/写作
appliedFilters-{mainPath}财务报告和审定财务报表shownFilters-{mainPath}因此过滤选择在重载中幸存;在没有历史记录的情况下默认为前8个过滤. - 父同步: 宣传每个应用过滤器的回转
useAppliedFilters[1],允许主机应用程序反应或推翻初始状态. - 应用过滤芯片: 从占位符中取出标签的Renders活动过滤器,用于显示格式值(通过akidate工具,数组,布林),并支持去除单个过滤器或清除全部.
- 动态过滤能见度数字 :
SelectShownFilters为每个适用的过滤器打开一个可搜索、可加成复选框的模式; 选择更新shownFilters并触发娱乐 以避免停滞状态. - 有条件过滤器: 可选
conditionalFiltersSchema使一个二次形式,其值合并为appliedFilters没有本地存储的持久性,每当计划改变时重建. - 辅助工具: 提供路径解析( S)
getPathFragments用于描述每个路径和树搜索帮助者(getTreeNodeByValue用于嵌入式选项查看. - 国际化脚手架: 装入静态 i18n 捆绑(EN/TR)通过
Akilocale用于组件复制,例如面板标题.
实施计划(用户经验重点)
-
过滤工作空间外壳
- 以更新的样式钩子来再造出后遗症布局,保留头标题,过滤选择触发器,被应用的过滤带,以及主过滤网格,这样现有的用户就觉得熟悉,同时允许将来的视觉tweaks.
- 整合
akilocale默认副本 (title,模式标签)并曝光主机应用程序的翻译密钥.
-
Schema 摄入和窗体渲染
- 接受一个外部
filterSchema(和可选)conditionalFiltersSchema)并将每个字段翻译为akiform部件,尊重特定组件道具,标签和占位符. - 默认只将“主”过滤器投放在第一个负载上(可配置计数),但尊重以后访问时的任何持续选择.
- 接受一个外部
-
用户输入和应用状态
- 镜像用户编辑为内部状态模型,同时通过提供的数据向主机排放JSON有效载荷
useAppliedFilterstuple so parent apps 接收犬科数据. - 将当前应用的过滤器显示为可移动芯片; 数值格式化应当透明地处理原始、阵列、布尔和类似日期的对象.
- 镜像用户编辑为内部状态模型,同时通过提供的数据向主机排放JSON有效载荷
-
过滤可见度管理
- 提供一种模式(使用
@akinon/ui-modal, (中文(简体) ),@akinon/ui-input, (中文(简体) ),@akinon/ui-pagination),列出了所有可用的过滤器,包括搜索、页码和复选框切换来控制能见度. - 坚持能见度选择和主形式顺序到本地存储,确保各会间有稳定的经验.
- 提供一种模式(使用
-
持久性战略
- 衍生出独特的本地存储键,使用调用器提供的前缀外加决定后缀(如散列图或路由),所以多个滤镜实例无法相撞.
- 支持可选的覆盖( 定制密钥 + 自定义主路径) , 同时总是附加我们的独特性盐 .
-
有条件的过滤器表面
- 渲染辅助设备
akiform主过滤器下方的段落conditionalFiltersSchema已存在, 当计划改变时, 重置其形式状态, 并将其值合并到释放的应用过滤器 JSON 中而不坚持存储 .
- 渲染辅助设备
-
批量动作导入过滤器( I)
- 保留快速重置的“ 清除所有” 动作, 持续更新 UI 状态、 存储和父调用 .
- 计划用于 CSV/XLS 导入的专用付费: 选项工具栏中显示按钮, 接受上传
@akinon/ui-upload,并将记录解析/正常化为应用过滤器(详情将在以后阶段执行).
-
测试和质量目标
- 覆盖所有交互式流量(窗体条目,芯片去除,模式切换,持久性,有条件的schema更改,CSV/XLS hooks),与Vitest和Testing Library并列,目标覆盖率为%-90%而不会倒退到现有的套房.
- 文档样本集成片段,使伙伴应用能够验证开发期间的行为.
价值 持久性persistValues(中文(简体) )
默认情况下, 字段值和活动过滤按钮会被写入本地存储
并在下一个山上恢复。 设定 persistValues={false} 当过滤器有
从主机供应的值( 例如从 API 上装过滤器) 开始 :
<Akifilter
filterSchema={filterSchema}
storageNamespace="saved-filters"
persistValues={false}
defaultValues={savedFilters}
onValuesChange={setFilters}
/>
- 数值和按钮状态从不读取或写入;窗体从
方案默认 +
defaultValues,按钮开始不活动. - 设置道具前所存储的值被忽略,而不是被删除.
- 可见-场(和分层可见度)持久性不受影响.
- 离开道具保持今天的行为
true) (中文(简体) ). persistValues财务报告和审定财务报表defaultValues在挂载上读取; 稍后更改 不重设窗体。 当值来自 API, 渲染Akifilter只有在他们装上子弹之后 转动persistValues关闭后 挂载停止进一步写入, 但保留已经恢复的内容 .
页脚
footer 将主机内容置入过滤卡内, 位于每个字段以下
节。 传递一个节点或接收函数 { values } (单位:千美元)
onValuesChange 形状,而不是被解除)以有条件地渲染。 恶性结果
(单位:千美元)null, (中文(简体) ), undefined, (中文(简体) ), false, (中文(简体) ), '', (中文(简体) ), 0) 使无:
<Akifilter
filterSchema={filterSchema}
footer={({ values }) =>
Object.keys(values).length > 0 ? <Button>Save as rule</Button> : null
}
/>
脚印坐在表外,所以一个按钮从不提交.
自定义标题
title 替换默认翻译的“Filters”标题。 通过一个字符串或一个
节点; 通过 null, (中文(简体) ), false 或者说 '' 隐藏标题,只保留
工具栏 :
<Akifilter filterSchema={filterSchema} title="Order Filters" />
区域
申报的字段 type: 'section' 转换为相撞面板
主过滤网格. 区块内的每个字段都与
顶级过滤器,所以通过 onValuesChange
并坚持像普通过滤器一样 在当地储存.
const filterSchema = [
{ key: 'sku', type: 'text', label: 'SKU', config: { visible: true } },
{
key: 'excludeSection',
type: 'section',
label: 'Exclude Filters',
isExcludeSection: true,
fields: [{ key: 'excludeSku', type: 'text', label: 'Exclude SKU' }]
}
];
区旗
| 旗帜 | 效果 |
|---|---|
defaultExpanded | false 启动面板倒塌. |
isExcludeSection | 用于部分字段的芯片与排除型号(红色芯片+排除图标)一起渲染. |
selectableFields | 添加一个漏斗按钮,打开每个分区的能见度模式. |
enableImportCsv | 将 CSV 导入按钮添加到区头。 要求数 onSectionImportCsv。 。 。 . |
enableImportXls | 将 XLS/XLSX 导入按钮添加到区域标题中。 要求数 onSectionImportXls。 。 。 . |
只有Akifilter读取这些旗帜.
isExcludeSection财务报告和审定财务报表selectableFields于SectionField内@akinon/akiform-builder历史 理由和拥有自己的建筑装置;enableImportCsv编号 :enableImportXls是Akifilter自己的道具,并到达一个建造者制造的路段 结束field().extend({ enableImportCsv: true }),这是任何新的 Akifilter只属于道具. 见附注SectionField在那个包裹里types.ts。 。 。 .
持久性
区值存储于同一下 …:values 本地存储条目为
顶层过滤器并在下个挂载上再加水,所以页面刷新保存
不包括填入的过滤器。 每个科的能见度选择(selectableFields(中文(简体) )
单独存放于 …:section:<sectionKey>。 。 。 .
存储密钥从 顶级 只有字段签名, 所以编辑
a 区域字段不会使条目无效(而现有条目存有)
升级)。 旧图中的定值被否决为: a
其形状不能适应当前状态的持久价值 type编号 :mode 实值
抛出而不是还原——例如,a留下的数组
select编号 :multiple 字段不输入到现在的字段 text。 。 。 . file
字段从未恢复,因为 File 无法活下来 JSON
连载.
外地可见度
onVisibleFieldsChange 只报告顶级字段。 跟随什么
区域完成,通过 onSectionVisibleFieldsChange - 它收到该部分的
key 及其可见字段的密钥,在列表上起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起起.
const handleSectionVisibleFieldsChange = useCallback(
(sectionKey: string, keys: string[]) =>
setSectionVisibleKeys(current => ({ ...current, [sectionKey]: keys })),
[]
);
<Akifilter
filterSchema={filterSchema}
onSectionVisibleFieldsChange={handleSectionVisibleFieldsChange}
/>;
对a selectableFields 一节按该节的能见度模式键;
任何其它章节都规定其所有领域并报告每个关键。 留着
处理者的身份稳定,就像 onVisibleFieldsChange: 一个新的函数
每一个内容都用一个不变的清单重新通知.
节级 CSV / XLS 导入
一节可以在崩溃页眉中显示自己的文件导入按钮
与顶级工具栏提供的价格相同 enableImportCsv 编号 :
onImportCsv,并有条件地与
selectableFields 漏斗声。 这通常用于排除一套大型的
通过上传文件而不是逐一输入值来记录.
按钮只在 两者 一半是存在的:
区域以及组件上的匹配处理器。 处理者收到
章节 key 首先,一个处理器可以服务每个区.
<Akifilter
filterSchema={[
{
key: 'excludeSection',
type: 'section',
label: 'Exclude Filters',
isExcludeSection: true,
enableImportCsv: true,
enableImportXls: true,
fields: [{ key: 'excludeSku', type: 'text', label: 'Exclude SKU' }]
}
]}
onSectionImportCsv={(sectionKey, file) => uploadExcludeFile(sectionKey, file)}
onSectionImportXls={(sectionKey, file) => uploadExcludeFile(sectionKey, file)}
/>
Akifilter 从未读取或剖析过文件—— 它只显示取取者和手
页:1 File 到主机应用程序。 要将上传显示为活动过滤器, 请输入
它回到过去 externalAppliedFilters (一组) isExclude: true 打开芯片
与排除的样式相匹配,并清除它 onRemoveExternalFilter。 。 。 .
自动导入组合按钮 selectableFields: 漏斗已导出
在同一个标题动作组内的文件按钮之后。 鼠标点击和
输入的按键被停止 从该组出动, 因此激活一个信头
动作从不切换其下方的面板.
与构建者API:
field()
.key('excludeSection')
.type('section')
.label('Exclude Filters')
.isExcludeSection(true)
// Akifilter's own flags travel through `extend()`; `isExcludeSection` and
// `selectableFields` predate it and keep their setters.
.extend({ enableImportCsv: true, enableImportXls: true })
.fields([field().key('excludeSku').type('text').label('Exclude SKU').build()])
.build();
本地化
区域标题动作副本 生活于 section.actions 命名空间
(单位:千美元)importCsv, (中文(简体) ), importXls, (中文(简体) ), importCsvTooltip, (中文(简体) ), importXlsTooltip) (中文(简体) ). 工具提示
密钥插入 {{section}} 与部分的标签.
外地标签
一个字段 label 驱动其形式输入。 有两个可选道具能超过一个
所以芯片和拾取器可以说一些不同的东西
输入 :
| Prop | 覆盖 | 倒计时 |
|---|---|---|
appliedLabel | 应用过滤器芯片(及其取出按钮的可访问名称). | label → placeholder → key |
visibilityLabel | "选择可见过滤器"模式中的字段行. | label → placeholder → key |
const filterSchema: AkifilterSchema = [
{
key: 'orderNo',
type: 'text',
label: 'Order No', // form input
appliedLabel: 'Order number', // chip: "Order number: 1001"
visibilityLabel: 'Order reference no' // modal row
},
{
key: 'excludeSection',
type: 'section',
label: 'Exclude Filters',
isExcludeSection: true,
fields: [
{
key: 'excludeStatus',
type: 'text',
label: 'Status',
// The chip is rendered outside the section, so it carries the context
// the section header would otherwise provide.
appliedLabel: 'Excluded status'
}
]
}
];
注释:
-
两个道具都是可选的. 一个既非行为又不完全如前的领域, 因此,把它们添加到一个领域 永远不会影响其他计划.
-
儿童科也支持他们,包括在排除的科内.
-
可见模式的搜索框匹配
visibilityLabel, (中文(简体) ),label, (中文(简体) ),placeholder财务报告和审定财务报表key,所以一个被覆盖的球场 仍然可以找到在任一 名称. -
Prop既不影响窗体输入本身的标签,也不影响其可访问的名称——使用
label对于这个. -
存储按字段键
key,从来没有通过任何标签,所以重命名或 压倒性标签不会使持续存在的价值观或能见度失效 选择. -
它们是Akifilter自己的道具,不是共享形式计划的一部分. 与 流利的建筑师,他们通过它的通用
extend()密舱 :import { field } from '@akinon/akiform-builder'; field() .key('orderNo') .type('text') .label('Order No') .extend({ appliedLabel: 'Order number' }) .build();尽管建设者对过滤器一无所知 Akifilter在建筑商的道具上宣布
FieldExtensions接口,以及extend()接受 仅限 已声明的密钥 — 类型错误或类型错误是编译 错误, 和一个想要将自己的元数据挂入字段的应用程序 以同样方式宣布:declare module '@akinon/akiform-builder' { interface FieldExtensions { requestKey?: string; } }AkiformBuilder忽略了全部内容——它使表单标签来自label一个人.
见 With Distinct Labels 故事书故事为活例.
多值过滤器和可切换过滤器类型
框外输入标记
A 类 select 字段为 mode: 'tags' 没有选项是自由形式的多值
输入:输入一个值,按 Enter 键将其变成可移动标记,重复。 这个
应用芯片加入条目 , 。 。 。 .
{
key: 'keywords',
type: 'select',
label: 'Keywords',
mode: 'tags',
options: []
}
mode 是存储签名的一部分, 因此在单个
和多值模式使其持续输入无效,而不是恢复
形状不相容.
一个字段,几个芯片appliedChips(中文(简体) )
默认情况下,一个字段会贡献一个应用过滤芯片。 拥有的字段 数个同时过滤器——每个过滤器类型一个桶,这个范围读取得更好: 两种芯片——可以自己生产:
{
key: 'attributeName',
type: 'custom',
label: 'Attribute Name',
// Value shape is the field's own business, e.g.
// { mode: 'exact', buckets: { contains: ['a', 'b'], exact: ['c'] } }
appliedChips: ({ field, value, formValues }) => [
{ id: 'contains', label: 'Attribute Name (Contains)', value: 'a, b' },
{ id: 'exact', label: 'Attribute Name (Exact match)', value: 'c' }
],
// Return the value the field should hold after the chip is removed,
// or `null` to clear the field.
onRemoveAppliedChip: ({ field, value, id }) => dropBucket(value, id),
render: ({ control }) => <MyInput control={control} />
}
| Prop | 行为 |
|---|---|
appliedChips | 以每个返回条目一个芯片来取代字段的单片. 返回时 [] "现在没有筹码" 每个条目是 { id, value, label?, isExclude? }· ; label 默认字段应用标签, isExclude 字段是否为排除部分. |
onRemoveAppliedChip | 将一个芯片的 × 重新映射到一个新的字段值, 由 Akifilter 执行, 持续并释放 。 没有它芯片就无法切除. |
id 对于同一逻辑输入和域内的独特性,必须是稳定的。 芯片
键是 <field key>::<chip id> 内部,并在第一时间拆分
分隔符,所以一个id可能包含 :: ——字段密钥可能不会.
appliedChips 只在字段本身的值是非空的时才被调用
空地规则压制平地芯片(null编号 :undefined空白的绳子,
一个空数组)也压制这些。 使用 formValues 改为 格式 芯片(a)
单位或由兄弟会球场持有的模式,而不是从兄弟会兄弟会中获取
这个领域什么也没有.
有了流利的建造器 两种道具都和标签一样
覆盖 : field().….extend({ appliedChips, onRemoveAppliedChip })。 。 。 .
因为每个芯片都来源于现场 窗体值, 坚持不懈的出现
免费: Akifilter 存储和再水合复合值与其他任何数值一样
一个,和 Clear all 和任何其他人一样清场。 没有什么是必须照镜子的
输入主机状态或由应用程序写入存储.
声明 appliedChips 也告诉存储层, 字段拥有
值形状,因此一个复合(对象)值被再水化而不是被
作为计划漂移而被拒绝——同样的豁免 type: 'custom' 获得。 没有
道具,仅限 custom 字段可能会在重新装入时持有对象值.
用户可以切换的过滤器
一些过滤器带有 类型 旁边的值 — 包含 / 精确匹配 /
开头是 —— 每个类型根据自己请求的密钥和几种类型
可以同时活动. 这个 With Tag Type Selector 故事书故事
执行以上棋子上的全部流:
| 关切 | 机制 |
|---|---|
| 输入( tags + 右侧的类型切换器) | A 类 custom 字段。 把它绑起来 useController({ control: renderProps.control, name })。 。 。 . |
| 国家所在的地方 | 每型有一桶的形态值加上活性类型——所以Akifilter坚持并重新将所有活性类型包括在内. |
| 每个类型一个芯片,每个芯片都有自己的标签 | appliedChips。 。 。 . |
| 删除单一类型 | onRemoveAppliedChip,返回没有该桶的值(null 当最后一个去. |
| 在请求密钥上映射桶 | 主机逻辑,因为一个逻辑过滤器可以同时放出数个密钥. |
故事的流传表明:
- 与
Contains活动, 输入filter a财务报告和审定财务报表filter b生产Attribute Name (Contains): filter a, filter b。 。 。 . - 切换类型 离开该桶与自己的芯片 并显示新的 类型(空)桶.
- 输入
filter c添加Attribute Name (Exact match): filter c,则 有效载荷携带两个请求键. - 回转再次显示输入中较早的桶.
- 页面刷新恢复每桶 财务报告和审定财务报表 活动类型.