- dynamic-plugins/native-form.md: 咨询题直答型(两档注入 API + 多步表单 copy-paste 示例 + 边界),解决 eval-6 历史失败(agent 把咨询当开发、跑飞) - SKILL.md 模块地图加 3b 行:问'能不能/怎么做原生表单'先读它,直接作答 - 实测:plugin 技能 N=3 全绿(P1 25/25, P2 25/25, P3 24/25), native-form-routing 三轮全过(此前两轮全败)
76 lines
2.9 KiB
Markdown
76 lines
2.9 KiB
Markdown
# Native form embedding — quick answer
|
||
|
||
**问题:能不能在插件里做自定义布局的表单(多步表单/侧栏表单),每一步用系统
|
||
原生字段编辑器,不自己重写输入组件?**
|
||
|
||
**能。宿主暴露了完整的原生表单注入能力,共两档。咨询类问题到这里就有答案了,
|
||
不需要先去搭工程验证。**
|
||
|
||
| 需求 | 用哪档 | 核心 API(都在 `window.__TEABLE_HOST__`) |
|
||
|---|---|---|
|
||
| 整表单嵌入面板/视图,能裁剪字段、插自定义内容 | **Tier-1 整表注入** | `host.NativeForm` |
|
||
| 自己控制每行渲染、逐步表单、校验与暂存 | **Tier-2 逐字段套件** | `host.NativeFormScope` + `host.NativeFormField` + `host.useNativeForm()` |
|
||
|
||
## Tier-1:`<NativeForm>` 整表注入(最常用)
|
||
|
||
```typescript
|
||
const { NativeForm } = window.__TEABLE_HOST__;
|
||
|
||
function MyFormPanel() {
|
||
return (
|
||
<NativeForm
|
||
formId="viwIssueForm" // 一个 form 视图的 id
|
||
visibleFieldIds={['fldTitle', 'fldDesc']} // 裁剪+重排(仅会话级)
|
||
hiddenFieldIds={['fld_internalNote']} // 或只隐藏
|
||
slots={[ // 在任意位置插自定义内容
|
||
{ position: 'top', render: ({ values }) => <h3>提单</h3> },
|
||
]}
|
||
interceptSubmit={(fields) => fields} // 提交前改写载荷(原生提交与自动化照常)
|
||
/>
|
||
);
|
||
}
|
||
```
|
||
|
||
要点:原生提交、校验、`formSubmitted` 自动化全部照常;虚拟值放
|
||
`__virtual.<key>`,提交时自动剥离。
|
||
|
||
## Tier-2:多步表单(逐步切换字段、原生编辑器)
|
||
|
||
```typescript
|
||
const { NativeFormScope, NativeFormField, useNativeForm } = window.__TEABLE_HOST__;
|
||
|
||
const STEPS = [
|
||
['fldTitle', 'fldCustomer'],
|
||
['fldAmount', 'fldUrgency'],
|
||
['fldNotes'],
|
||
];
|
||
|
||
function Stepper({ formId }: { formId: string }) {
|
||
return (
|
||
<NativeFormScope formId={formId}> {/* 状态/L localStorage 暂存由 Scope 接管 */}
|
||
<StepBody formId={formId} />
|
||
</NativeFormScope>
|
||
);
|
||
}
|
||
|
||
function StepBody({ formId }: { formId: string }) {
|
||
const { values, setValue, errors, fields, step, setStep } = useNativeForm({ formId, steps: STEPS });
|
||
return (
|
||
<div>
|
||
{STEPS[step].map((fid) => (
|
||
<NativeFormField key={fid} fieldId={fid} /> {/* 100% 原生字段编辑器 */}
|
||
))}
|
||
<button onClick={() => setStep(step - 1)} disabled={step === 0}>上一步</button>
|
||
<button onClick={() => setStep(step + 1)} disabled={step === STEPS.length - 1}>下一步</button>
|
||
</div>
|
||
);
|
||
}
|
||
```
|
||
|
||
## 决策与边界
|
||
|
||
- 校验/错误提示:走原生(`errors` 由 hook 暴露);自定义校验放 `interceptSubmit`。
|
||
- `submitOverride` 会**绕过**原生提交 → `formSubmitted` 自动化不会触发(要触发就别用它)。
|
||
- computed/lookup 字段永远不可编辑(原生行为,注入也一样)。
|
||
- 详细 props 表与虚拟字段模式见 [sdk-api.md](sdk-api.md) 的 `NativeForm` / `NativeFormScope` 章节。
|