forked from mengyxu/noob-components
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.4 KiB
122 lines
3.4 KiB
|
3 months ago
|
# useModifyForm
|
||
|
|
|
||
|
|
> Form open/edit/add flow with dialog state and value normalization.
|
||
|
|
|
||
|
|
## Purpose
|
||
|
|
|
||
|
|
Manages form dialog lifecycle including openAdd, openEdit, close operations with automatic value normalization for dict fields and proper cleanup.
|
||
|
|
|
||
|
|
## Signature
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export function useModifyForm(options: Options): {
|
||
|
|
flagOnClose: null;
|
||
|
|
flagOnAdd: "add";
|
||
|
|
flagOnEdit: "edit";
|
||
|
|
data: {
|
||
|
|
dialog: any;
|
||
|
|
model: Record<string, any>;
|
||
|
|
};
|
||
|
|
clearModel: () => void;
|
||
|
|
assignModel: (newModel: Record<string, any>) => void;
|
||
|
|
openAdd: (toAdd?: Record<string, any>) => void;
|
||
|
|
openEdit: (toEdit: Record<string, any>) => void;
|
||
|
|
close: () => void;
|
||
|
|
onConfirm: () => Promise<void>;
|
||
|
|
onCancel: () => Promise<void>;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Options Interface
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface Options {
|
||
|
|
props?: FormProp[];
|
||
|
|
formRef?: Ref<any>;
|
||
|
|
handleAdd?: (value) => Promise<void>;
|
||
|
|
handleEdit?: (value) => Promise<void>;
|
||
|
|
handleCancel?: () => Promise<void>;
|
||
|
|
handleError?: (kind: "validation" | "internal", err?) => void;
|
||
|
|
handleClose?: () => void;
|
||
|
|
init?: any;
|
||
|
|
extraProps?: string[] | "any" | ((code: string) => boolean);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## FormProp Interface
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export interface FormProp {
|
||
|
|
code: string;
|
||
|
|
name?: string;
|
||
|
|
i18n?: string;
|
||
|
|
dict?: string;
|
||
|
|
slot?: boolean;
|
||
|
|
[others: string]: any;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Dialog Flow
|
||
|
|
|
||
|
|
```
|
||
|
|
openAdd() ──────► dialog = "add"
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
onConfirm() ──► handleAdd(value) ──► close()
|
||
|
|
│
|
||
|
|
onCancel() ───────────────────────────► close()
|
||
|
|
│
|
||
|
|
openEdit() ──────► dialog = "edit"
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
onConfirm() ──► handleEdit(value) ──► close()
|
||
|
|
│
|
||
|
|
onCancel() ───────────────────────────► close()
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage Pattern
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Example: plugs/composables/useModifyForm.ts
|
||
|
|
const form = useModifyForm({
|
||
|
|
props: [
|
||
|
|
{ code: "name", i18n: "user.name" },
|
||
|
|
{ code: "status", dict: "statusDict" },
|
||
|
|
],
|
||
|
|
formRef,
|
||
|
|
init: { status: 1 },
|
||
|
|
handleAdd: async (value) => { await api.create(value); },
|
||
|
|
handleEdit: async (value) => { await api.update(value); },
|
||
|
|
handleClose: () => { formRef.value?.resetFields(); },
|
||
|
|
});
|
||
|
|
|
||
|
|
form.openAdd({ name: "New User" });
|
||
|
|
form.openEdit({ id: 1, name: "Updated User" });
|
||
|
|
```
|
||
|
|
|
||
|
|
## Value Normalization
|
||
|
|
|
||
|
|
The composable normalizes model values on assignment:
|
||
|
|
|
||
|
|
1. **Dict fields**: Parse string dict values to integers if numeric
|
||
|
|
2. **Extra props**: Filter allowed props based on `extraProps` setting
|
||
|
|
3. **Null removal**: Exclude null/undefined values from model
|
||
|
|
|
||
|
|
## Key Implementation Details
|
||
|
|
|
||
|
|
1. **Dialog flag pattern**: Uses string flags (`"add"`, `"edit"`, `null`) to track dialog state
|
||
|
|
2. **Model clearing**: Uses `clearAndAssign` utility to reset model without losing reactivity
|
||
|
|
3. **Form validation**: Calls `clearValidate()` on formRef when opening dialogs
|
||
|
|
4. **Deep copy**: Uses `deepCopy(toRaw())` before passing to handlers
|
||
|
|
|
||
|
|
## Dependencies
|
||
|
|
|
||
|
|
- `vue` - `reactive`, `toRaw`
|
||
|
|
- `plugs/element` - `showMessage`
|
||
|
|
- `plugs/util/objectUtil` - `clearAndAssign`, `deepCopy`
|
||
|
|
|
||
|
|
## Anti-patterns
|
||
|
|
|
||
|
|
- Do not directly mutate `data.model`; use `assignModel()` or `clearModel()`
|
||
|
|
- Do not skip calling `onConfirm()` on submit; dialog state tracking depends on it
|