openai/chatkit-python

Public

mirrored from https://github.com/openai/chatkit-pythonAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2e1209a2c4f4957e7f783eceeb79655c9e38d036

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

docs/guides/add-features/create-custom-forms.md

69lines · modecode

1# Create custom forms
2
3Wrap widgets that collect user input in a `Form` to have their values automatically injected into every action triggered inside that form. The form values arrive in the action payload, keyed by each field’s `name`.
4
5- `<Select name="title" />` → `action.payload["title"]`
6- `<Select name="todo.title" />` → `action.payload["todo"]["title"]`
7
8```jsx
9<Form
10 direction="col"
11 onSubmitAction={{
12 type: "update_todo",
13 payload: { id: todo.id },
14 }}
15>
16 <Title value="Edit Todo" />
17 <Text value="Title" color="secondary" size="sm" />
18 <Text
19 value={todo.title}
20 editable={{ name: "title", required: true }}
21 />
22 <Text value="Description" color="secondary" size="sm" />
23 <Text
24 value={todo.description}
25 editable={{ name: "description" }}
26 />
27 <Button label="Save" submit />
28</Form>
29```
30
31On the server, read the form values from the action payload. Any action originating from inside the form will include the latest field values.
32
33```python
34from collections.abc import AsyncIterator
35from chatkit.server import ChatKitServer
36from chatkit.types import Action, ThreadMetadata, ThreadStreamEvent, WidgetItem
37
38
39class MyChatKitServer(ChatKitServer[RequestContext]):
40 async def action(
41 self,
42 thread: ThreadMetadata,
43 action: Action[str, Any],
44 sender: WidgetItem | None,
45 context: RequestContext,
46 ) -> AsyncIterator[ThreadStreamEvent]:
47 if action.type == "update_todo":
48 todo_id = action.payload["id"]
49 # Any action that originates from within the Form will
50 # include title and description
51 title = action.payload["title"]
52 description = action.payload["description"]
53
54 # ...
55```
56
57### Validation
58
59`Form` uses basic native form validation; it enforces `required` and `pattern` on configured fields and blocks submission when any field is invalid.
60
61We may add new validation modes with better UX, more expressive validation, and custom error display. Until then, widgets are not a great medium for complex forms with tricky validation. If you need this, a better pattern is to use client-side action handling to trigger a modal, show a custom form there, then pass the result back into ChatKit with `sendCustomAction`.
62
63### Treating `Card` as a `Form`
64
65You can pass `asForm=True` to `Card` and it will behave as a `Form`, running validation and passing collected fields to the Card’s `confirm` action.
66
67### Payload key collisions
68
69If there is a naming collision with some other existing pre-defined key on your payload, the form value will be ignored. This is probably a bug, so we’ll emit an `error` event when we see this.
70