Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions docs/guides/form-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ Records audio using device microphone.
**Expected Schema:**
```json
{
"type": "string",
"type": "object",
"format": "audio",
"title": "Voice Note"
}
Expand Down Expand Up @@ -670,7 +670,7 @@ Records video using device camera.
**Expected Schema:**
```json
{
"type": "string",
"type": "object",
"format": "video",
"title": "Instructional Video"
}
Expand Down Expand Up @@ -699,12 +699,12 @@ Records video using device camera.

### File Selection

Allows users to select files from device storage.
Allows users to pick an arbitrary file from device storage (documents, exports, etc.). Behaves like other **attachment** fields: the observation stores a **basename** (stable key under app `attachments/`) plus portable metadata; the binary syncs through the attachment pipeline separately from the observation JSON.

**Expected Schema:**
```json
{
"type": "string",
"type": "object",
"format": "select_file",
"title": "Upload Document"
}
Expand All @@ -719,15 +719,15 @@ Allows users to select files from device storage.
```

**Renderer Behavior:**
- Opens device file picker
- User selects file from storage
- Stores file reference and metadata
- File is uploaded as attachment
- Opens the system file picker
- Copies the file into **`attachments/draft/`** with a generated basename (mobile)
- Persists **`filename`** (basename), **`timestamp`**, and **`metadata`** (`mimeType`, `size`, `extension`, optional **`originalFileName`** for display)
- Shows **only the display filename** in the form (no thumbnail or inline preview)

**Platform Constraints:**
- File type restrictions depend on platform
- Large files may take time to upload
- Storage permissions required
- Allowed file types depend on OS picker and Formulus configuration
- Large files affect sync time and storage
- Storage / privacy permissions depend on platform

### QR Code / Barcode Scanner

Expand Down Expand Up @@ -1031,7 +1031,7 @@ Show field when boolean is true:

### Multimedia Capture

Forms can include fields for capturing photos, audio, and video. These are handled as attachments and synchronized separately from observation metadata.
Forms can include fields for capturing photos, audio, and video, and for attaching generic files (`select_file`). These binaries are handled as **attachments** and synchronized separately from observation metadata (observation JSON holds basename + metadata).

### Location Capture

Expand Down
4 changes: 3 additions & 1 deletion docs/reference/form-specifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,11 @@ See the full schema options and examples in [Custom Extensions](../guides/custom

#### File Selection

Generic attachment via document picker. Use **`type: object`** with **`format: select_file`** (Formplayer stores basename + portable metadata; no inline preview).

```json
{
"type": "string",
"type": "object",
"format": "select_file",
"title": "Upload Document"
}
Expand Down
31 changes: 26 additions & 5 deletions docs/reference/formplayer-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -558,13 +558,13 @@ All custom formats are registered in Ajv and have corresponding custom renderers
| `gps` | `string` or `object` | `GPSQuestionRenderer` | GPS coordinates |
| `signature` | `object` | `SignatureQuestionRenderer` | Signature pad |
| `qrcode` | `string` or `object` | `QrcodeQuestionRenderer` | Barcode scanner |
| `audio` | `string` or `object` | `AudioQuestionRenderer` | Audio recording |
| `video` | `string` or `object` | `VideoQuestionRenderer` | Video recording |
| `select_file` | `string` or `object` | `FileQuestionRenderer` | File picker |
| `audio` | `object` | `AudioQuestionRenderer` | Audio recording |
| `video` | `object` | `VideoQuestionRenderer` | Video recording |
| `select_file` | `object` | `FileQuestionRenderer` | Generic file attachment (picker) |

### Format Registration

**Ajv Registration** (App.tsx:544-551):
**Ajv Registration** (App.tsx):
```typescript
ajv.addFormat('photo', () => true); // Accepts any value
ajv.addFormat('qrcode', () => true);
Expand Down Expand Up @@ -608,6 +608,27 @@ export const customRenderers = [
}
```

**File (`select_file`):**

Use `type: object` with `format: select_file`. The Formplayer stores **basename-only** attachment keys and portable metadata (mime type, size, extension, optional original picker display name). The native app copies the picked file into **`attachments/draft/`** (same layout as photos). The UI shows the **filename only**—there is no embedded preview.

```json
// Schema
{
"supporting_doc": {
"type": "object",
"format": "select_file",
"title": "Supporting document"
}
}

// UI Schema
{
"type": "Control",
"scope": "#/properties/supporting_doc"
}
```

**GPS:**
```json
// Schema (string format)
Expand Down Expand Up @@ -638,7 +659,7 @@ export const customRenderers = [
**Key Points:**
- ✅ No special UI schema required (standard `Control` is sufficient)
- ✅ Format must be specified in schema
- ✅ Type can be `string` or `object` (depends on format)
- ✅ Attachment-backed builtins (**`photo`**, **`audio`**, **`video`**, **`select_file`**) use **`type: object`** in current Formplayer (match JSON Forms testers in `App.tsx`). Other formats may accept `string` or `object` (e.g. **`gps`**, **`qrcode`**).
- ✅ Custom renderer handles all UI and interaction

---
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/formplayer.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ Formplayer includes core question type renderers:
- `SignatureQuestionRenderer`: Digital signature
- `AudioQuestionRenderer`: Voice recording
- `VideoQuestionRenderer`: Video recording
- `FileQuestionRenderer`: File attachment
- `FileQuestionRenderer`: Generic file attachment (`format: select_file`, `type: object`) — document picker, basename persistence like photos; **filename-only** UI (no preview)
- `SubObservationQuestionRenderer`: Embedded sub-observation repeats (`format: sub-observation`) — nested `openFormplayer` with `subObservationMode`

### Custom Renderers
Expand Down
Loading