# OKMFlow Workflow Engine 1.8 — Workflow Forms

> Workflow forms allow users to interact with process tasks. They are defined in XML and associated to the Task node via the **Form definition** property. Unlike OpenKM metadata groups, workflow forms are not tied to any group or field prefix: field names are free.

## Related references

- `llms-full-okmflow-*.txt` — Workflow engine: nodes, transitions, Groovy scripts, WorkflowUtils, WorkflowBeans.

---

## Workflow Form Definition

Workflow forms are based on a formal XML definition. The DTD (Document Type Definition) defines the structure and valid elements and attributes.

### DTD version

```
workflow-form-1.1.dtd
```

### Document structure

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE workflow-form PUBLIC "-//OpenKM//DTD Workflow Form 1.0//EN"
                                "https://www.openkm.com/dtd/workflow-form-1.0.dtd">
<workflow-form>
  <!-- field elements -->
</workflow-form>
```

If the server has no Internet access, a local DTD reference can be used:

```xml
<!DOCTYPE workflow-form PUBLIC "-//OpenKM//DTD Workflow Form 1.0//EN"
                                "file:///home/openkm/workflow-form-1.0.dtd">
```

### Field naming rules

- The `name` attribute of each field must be **unique** within the same form.
- There are no prefix restrictions: names are free (`price`, `approvedBy`, `start_date`, etc.).
- Avoid special characters; it is recommended to use only `[0-9a-zA-Z_]`.
- **Both `label` and `name` are required on every field type**, even fields that store no data (e.g. `separator`). Omitting either attribute throws a `ParseException`.

### `data` attribute

The `data` attribute is available on most fields. When present, it acts as an identifier to **load the field value from the workflow context**. The Action node that precedes the task must have placed the corresponding object in the context under that name.

```groovy
// In the Action node prior to the task:
import com.openkm.bean.form.*;
Input priceInput = new Input();
priceInput.setValue("1500.00");
context.put("price", priceInput);
```

```xml
<!-- In the form: will show "1500.00" pre-filled -->
<input label="Price" name="price" data="price" readonly="true" />
```

### Complete example

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE workflow-form PUBLIC "-//OpenKM//DTD Workflow Form 1.0//EN"
                                "https://www.openkm.com/dtd/workflow-form-1.0.dtd">
<workflow-form>
  <input label="Purchase price"          name="price"       data="price"       readonly="true" />
  <textarea label="Purchase description" name="description" data="description" readonly="true" />
  <select label="Decision" name="decision" type="simple">
    <option label="Approve" value="approve" />
    <option label="Reject"  value="reject" />
  </select>
  <input label="Comments" name="comments" />
  <button name="approve" label="Approve" transition="approve" color="success" />
  <button name="deny"    label="Deny"    transition="deny"    color="danger" />
</workflow-form>
```

---

## Workflow Fields

Available field types inside `<workflow-form>`:

| Field type      | Tag           | Stores data | Description |
|-----------------|---------------|-------------|-------------|
| Input           | `<input>`     | Yes | Single-line text, date, link, folder, or password |
| CheckBox        | `<checkbox>`  | Yes | Boolean toggle (true/false) |
| Select          | `<select>`    | Yes | Dropdown or multi-select list |
| SuggestBox      | `<suggestbox>`| Yes | AJAX autocomplete text field |
| TextArea        | `<textarea>`  | Yes | Multi-line text or HTML content |
| Button          | `<button>`    | No  | Submits the form and optionally follows a workflow transition |
| Upload          | `<upload>`    | No  | Uploads a document to OpenKM |
| Download        | `<download>`  | No  | Shows a download link for a document in OpenKM |
| Text            | `<text>`      | No  | Read-only label or static HTML |
| Separator       | `<separator>` | No  | Visual divider |
| VerticalPanel   | `<vpanel>`    | No  | Vertical layout container |
| HorizontalPanel | `<hpanel>`    | No  | Horizontal layout container |

Child elements (nested inside a field):

| Element   | Tag           | Parent(s)          | Description |
|-----------|---------------|--------------------|-------------|
| Option    | `<option>`    | `<select>`         | A selectable option within a Select field |
| Node      | `<node>`      | `<download>`       | A document reference (path or uuid) within a Download field |
| Validator | `<validator>` | `<input>`, `<checkbox>`, `<select>`, `<suggestbox>`, `<textarea>`, `<upload>`, `<download>` | Field-level validation rule |

### Element hierarchy

```
workflow-form
├── input        → validator*
├── checkbox     → validator*
├── select       → option*, validator*
├── suggestbox   → validator*
├── textarea     → validator*
├── button
├── upload       → validator*
├── download     → node+, validator*
├── text
├── separator
├── vpanel       → (all of the above)*
└── hpanel       → (all of the above)*
```

---

## Workflow Checkbox field

Represents a boolean value (true/false).

### Attributes

| Attribute     | Type    | Required | Default | Description |
|---------------|---------|----------|---------|-------------|
| `label`       | String  | Yes | — | Text shown as the field label in the UI. |
| `name`        | String  | Yes | — | Unique field identifier within the form. |
| `value`       | Boolean | No  | `false` | Initial checked state. Accepted values: `true` or `false`. |
| `data`        | String  | No  | — | Context variable name used to load the initial value dynamically. |
| `width`       | String  | No  | — | HTML element width. Use percentage values (e.g. `50%`) for KCenter UI. |
| `height`      | String  | No  | — | HTML element height. |
| `readonly`    | Boolean | No  | `false` | When `true`, prevents modification from the UI. |
| `visible`     | Boolean | No  | `true`  | When `false`, the field is hidden in the UI. |
| `description` | String  | No  | — | Descriptive text for the field. |

### Child elements

`<validator>`

### Example

```xml
<workflow-form>
  <checkbox label="Reviewed"  name="reviewed"  value="false" />
  <checkbox label="Urgent"    name="urgent"    data="isUrgent" readonly="true" />
</workflow-form>
```

---

## Workflow Button field

Buttons allow the user to complete the task, optionally following a workflow transition.

### Attributes

| Attribute      | Type    | Required | Default   | Description |
|----------------|---------|----------|-----------|-------------|
| `label`        | String  | Yes | — | Text shown on the button. |
| `name`         | String  | Yes | — | Unique field identifier within the form. |
| `transition`   | String  | No  | — | Workflow transition to follow when the button is clicked. If absent, the form is submitted without routing. |
| `confirmation` | String  | No  | — | Shows a confirmation popup with this message before submitting. |
| `validate`     | Boolean | No  | `true`  | When `false`, skips field validation on submit. |
| `style`        | Enum    | No  | `yes`   | Icon style. Values: `yes`, `no`, `add`, `delete`, `download`, `downloadZip`, `home`, `view`, `change`, `compact`, `clean`, `search`, `save`, `comment`. |
| `color`        | Enum    | No  | `success` | Button color. Values: `success`, `primary`, `secondary`, `danger`, `warning`, `info`, `light`, `dark`. |
| `width`        | String  | No  | — | HTML element width. Use percentage values for KCenter UI. |
| `visible`      | Boolean | No  | `true`  | When `false`, the button is hidden in the UI. |

### Example

```xml
<workflow-form>
  <input label="Comments" name="comments" />
  <button name="approve" label="Approve" transition="approve" color="success" style="yes" />
  <button name="deny"    label="Deny"    transition="deny"    color="danger"  style="no"
          confirmation="Are you sure you want to deny this request?" />
</workflow-form>
```

---

## Workflow Download field

Shows a download button that allows the user to download a document from OpenKM. Requires at least one `<node>` child element to identify the document.

### Attributes

| Attribute | Type    | Required | Default | Description |
|-----------|---------|----------|---------|-------------|
| `label`   | String  | Yes | — | Text shown as the field label in the UI. |
| `name`    | String  | Yes | — | Unique field identifier within the form. |
| `data`    | String  | No  | — | Context variable name used to load the node reference dynamically. When used, the `<node>` child can omit `uuid`/`path`. |
| `width`   | String  | No  | — | HTML element width. Use percentage values for KCenter UI. |
| `height`  | String  | No  | — | HTML element height. |
| `visible` | Boolean | No  | `true` | When `false`, the field is hidden in the UI. |

### Child elements

`<node>` (at least one required), `<validator>`

### Examples

**Static UUID:**

```xml
<workflow-form>
  <download name="contractDownload" label="Download contract">
    <node label="Contract" uuid="afb8ac33-912d-4515-e29b-1c01b693809a" />
  </download>
</workflow-form>
```

**Dynamic UUID via `data`** (the preceding Action node places the uuid in the context):

```xml
<workflow-form>
  <download name="docDownload" label="Download document" data="docRef">
    <node label="Document" />
  </download>
</workflow-form>
```

---

## Workflow Node element

Child element of `<download>`. Identifies the document to download by its path or UUID in OpenKM.

### Supported parent fields

`<download>`

### Attributes

| Attribute | Type   | Required | Default | Description |
|-----------|--------|----------|---------|-------------|
| `label`   | String | Yes | — | Text shown as the download link label. |
| `path`    | String | No  | — | OpenKM path of the document (e.g. `/okm:root/contracts/contract.pdf`). |
| `uuid`    | String | No  | — | UUID of the document in OpenKM. |

> **Note:** either `path` or `uuid` must be specified. When the `data` attribute is used in the parent `<download>`, the `<node>` can omit both — the value is loaded dynamically from the workflow context.

### Example

```xml
<download name="download" label="Download document">
  <node label="View document" uuid="afb8ac33-912d-4515-e29b-1c01b693809a" />
</download>
```

---

## Workflow Input field

Single-line text field. Supports free text, dates, URLs, OpenKM folder references, and passwords.

### Attributes

| Attribute     | Type   | Required | Default | Description |
|---------------|--------|----------|---------|-------------|
| `label`       | String | Yes | — | Text shown as the field label in the UI. |
| `name`        | String | Yes | — | Unique field identifier within the form. |
| `type`        | Enum   | Yes | `text` | Field data type: `text`, `date`, `link`, `folder`, `password`. |
| `value`       | String | No  | — | Default value. Dates use the format `yyyyMMddHHmmss`. |
| `data`        | String | No  | — | Context variable name used to load the initial value dynamically. |
| `width`       | String | No  | — | HTML element width. Use percentage values for KCenter UI. |
| `height`      | String | No  | — | HTML element height. |
| `placeholder` | String | No  | — | Placeholder text shown when the field is empty. |
| `description` | String | No  | — | Descriptive text for the field. |
| `readonly`    | Boolean| No  | `false` | When `true`, prevents modification from the UI. |
| `visible`     | Boolean| No  | `true`  | When `false`, the field is hidden in the UI. |
| `timeFormat`  | Enum   | No  | `none`  | For `date` type only: `hm` (hours and minutes), `h` (hours only), `none` (date only). |

### Input types

| Value      | Description |
|------------|-------------|
| `text`     | Free-text string. |
| `date`     | Date (and optionally time) picker. Stored as `yyyyMMddHHmmss`. |
| `link`     | Clickable URL stored as text. |
| `folder`   | Repository node reference (clickable link). Works for folders, documents, and records alike — the name `folder` is a historical artefact (the field was originally folder-only but was extended without renaming the value); a more accurate name would be `node`. |
| `password` | Password field (value is masked). |

> **Important:** when writing a `date`-type field's value into a metadata property group (`ws.propertyGroup.setProperties()` / `addGroup()`), pass `Input.getValue()` through **unchanged** — the property group validator requires the raw ISO 8601 basic pattern (`yyyyMMddHHmmss`) and rejects anything else (e.g. `yyyy-MM-dd`) with `errorCode=016` / `does not match ISO8601 basic pattern`. Reformatting is only safe when the result is stored under a **different** context key used purely for `${...}` display inside a Mail node's FreeMarker template — never for the value passed to `setProperties`/`addGroup`.

### Child elements

`<validator>`

### Example

```xml
<workflow-form>
  <input label="Invoice number" name="invoiceNumber" type="text">
    <validator type="req" />
  </input>
  <input label="Due date"       name="dueDate"       type="date" timeFormat="none" />
  <input label="Amount"         name="amount"        type="text">
    <validator type="req" />
    <validator type="dec" />
    <validator type="gt" parameter="0" />
  </input>
  <input label="Reference URL"  name="refUrl"        type="link" />
  <input label="Archive folder" name="archiveFolder" type="folder" />
  <!-- Field pre-filled from the workflow context -->
  <input label="Requester"      name="requester"     type="text" data="requesterName" readonly="true" />
</workflow-form>
```

---

## Workflow Select field

Simple or multiple-selection field. Options can be defined inline in XML, via a SQL query, or via a plugin class.

### Attributes

| Attribute       | Type    | Required | Default  | Description |
|-----------------|---------|----------|----------|-------------|
| `label`         | String  | Yes | — | Text shown as the field label in the UI. |
| `name`          | String  | Yes | — | Unique field identifier within the form. |
| `type`          | Enum    | Yes | `simple` | `simple` — single selection; `multiple` — multiple selections allowed. |
| `value`         | String  | No  | — | Default selected value. |
| `data`          | String  | No  | — | Context variable name used to load the initial value dynamically. |
| `optionsData`   | String  | No  | — | Context variable name used to load the option list dynamically. |
| `width`         | String  | No  | — | HTML element width. Use percentage values for KCenter UI. |
| `height`        | String  | No  | — | HTML element height. |
| `optionsQuery`  | String  | No* | — | SQL SELECT returning `(id, label)` pairs to populate options. |
| `filterQuery`   | String  | No** | — | SQL SELECT with `{0}` placeholder for typed input. Used when `suggestbox="true"`. |
| `valueQuery`    | String  | No** | — | SQL SELECT with `{0}` for the stored id. Resolves saved value to display label. Required when `filterQuery` is set. |
| `suggestbox`    | Boolean | No  | `false`  | When `true`, renders as inline filter-as-you-type instead of a dropdown. |
| `filterMinLen`  | Integer | No  | — | Minimum characters before filtering activates (used when `suggestbox="true"`). |
| `className`     | String  | No* | — | Fully-qualified class name of an `OptionSelectValues` plugin. |
| `parentElement` | String  | No  | — | Name of another `<select>` field whose value filters this field's options. |
| `description`   | String  | No  | — | Descriptive text for the field. |
| `readonly`      | Boolean | No  | `false`  | When `true`, prevents modification from the UI. |
| `visible`       | Boolean | No  | `true`   | When `false`, the field is hidden in the UI. |

\* `optionsQuery`, `className`, and inline `<option>` elements are mutually exclusive. Use exactly one approach.
\*\* `filterQuery` and `valueQuery` must be specified together when `suggestbox="true"` and not using `className`.

### Child elements

`<option>`, `<validator>`

### Examples

**Static options (inline):**

```xml
<select label="Priority" name="priority" type="simple">
  <option label="Low"    value="low" />
  <option label="Medium" value="medium" selected="true" />
  <option label="High"   value="high" />
</select>
```

**Multiple selection:**

```xml
<select label="Approvers" name="approvers" type="multiple">
  <option label="Manager"   value="manager" />
  <option label="Director"  value="director" />
  <option label="CFO"       value="cfo" />
</select>
```

**SQL-driven options:**

```xml
<select label="Country" name="country" type="simple"
        optionsQuery="SELECT CT_ID, CT_NAME FROM COUNTRY ORDER BY CT_NAME" />
```

**Plugin-driven options:**

```xml
<select label="Assigned to" name="assignee" type="simple"
        className="com.openkm.plugin.form.values.OptionSelectUserList" />
```

**Hierarchical (parent-child) selects:**

```xml
<select label="Category" name="category" type="simple">
  <option value="directives" label="Directives" />
  <option value="handbook"   label="Handbook" />
</select>

<select label="Sub-category" name="subcategory"
        type="simple" parentElement="category">
  <option value="benefits"    label="Benefits"    parentValue="directives" />
  <option value="eligibility" label="Eligibility" parentValue="directives" />
  <option value="basic"       label="Basic"       parentValue="handbook" />
  <option value="advanced"    label="Advanced"    parentValue="handbook" />
</select>
```

**Hierarchical with SQL:**

```xml
<select name="localidad" label="Localidad"
        optionsQuery="SELECT LOC_ID, LOC_NAME FROM LOCALIDAD" />
<select name="ubicacion" label="Ubicación" parentElement="localidad"
        optionsQuery="SELECT UBI_ID, UBI_NAME, UBI_LOC FROM UBICACION" />
```

---

## Workflow Separator field

Visual separator between fields. Does not store data.

### Attributes

| Attribute | Type   | Required | Default | Description |
|-----------|--------|----------|---------|-------------|
| `label`   | String | Yes | — | Text shown alongside the separator line in the UI. |
| `name`    | String | Yes | — | Unique field identifier within the form. |
| `width`   | String | No  | — | HTML element width. Use percentage values for KCenter UI. |
| `visible` | Boolean| No  | `true`  | When `false`, the separator is hidden in the UI. |

### Example

```xml
<workflow-form>
  <input label="Invoice number" name="invoiceNumber" type="text" />
  <input label="Amount"         name="amount"        type="text" />
  <separator label="Approval" name="sep_approval" />
  <checkbox label="Approved"    name="approved" />
  <input label="Approved by"    name="approvedBy"    type="text" />
</workflow-form>
```

---

## Workflow SuggestBox field

Text field with AJAX suggestions (autocomplete). Options are retrieved via a SQL query or a plugin class.

### Attributes

| Attribute      | Type    | Required | Default | Description |
|----------------|---------|----------|---------|-------------|
| `label`        | String  | Yes | — | Text shown as the field label in the UI. |
| `name`         | String  | Yes | — | Unique field identifier within the form. |
| `dialogTitle`  | String  | Yes | — | Title of the suggestion dialog window. |
| `filterMinLen` | Integer | Yes | — | Minimum number of characters the user must type before suggestions appear. |
| `filterQuery`  | String  | No* | — | SQL SELECT with a `{0}` placeholder for the typed input. Returns `(id, label)` pairs. |
| `valueQuery`   | String  | No* | — | SQL SELECT with a `{0}` placeholder for the stored id. Returns the display label for a saved value. |
| `className`    | String  | No* | — | Fully-qualified class name of a `SuggestBoxValues` plugin. |
| `value`        | String  | No  | — | Default value. |
| `data`         | String  | No  | — | Context variable name used to load the initial value dynamically. |
| `width`        | String  | No  | — | HTML element width. |
| `height`       | String  | No  | — | HTML element height. |
| `description`  | String  | No  | — | Descriptive text for the field. |
| `readonly`     | Boolean | No  | `false` | When `true`, prevents modification from the UI. |
| `visible`      | Boolean | No  | `true`  | When `false`, the field is hidden in the UI. |

\* Either (`filterQuery` + `valueQuery`) together **or** `className` alone is required.

### Child elements

`<validator>`

### Examples

**SQL-based:**

```xml
<suggestbox label="Country" name="country"
            filterMinLen="2" dialogTitle="Choose country"
            filterQuery="SELECT CT_ID, CT_NAME FROM COUNTRY WHERE CT_NAME LIKE '%{0}%' ORDER BY CT_NAME"
            valueQuery="SELECT CT_ID, CT_NAME FROM COUNTRY WHERE CT_ID = '{0}'" />
```

**Plugin-based:**

```xml
<suggestbox label="Assigned user" name="assignedUser"
            filterMinLen="1" dialogTitle="Choose user"
            className="com.openkm.plugin.form.values.SuggestBoxUserList" />
```

---

## Workflow Text field

Read-only element that displays static text or HTML. Does not store data.

### Attributes

| Attribute | Type   | Required | Default | Description |
|-----------|--------|----------|---------|-------------|
| `label`   | String | Yes | — | Text (or HTML) shown as a static label in the UI. HTML must be XML-encoded (e.g. `&lt;b&gt;text&lt;/b&gt;`). When the value is loaded via `data`, encoding is not needed. |
| `name`    | String | Yes | — | Unique field identifier within the form. |
| `data`    | String | No  | — | Context variable name used to load the text dynamically. When used, HTML encoding is not required. |
| `width`   | String | No  | — | HTML element width. Use percentage values for KCenter UI. |
| `height`  | String | No  | — | HTML element height. |
| `visible` | Boolean| No  | `true`  | When `false`, the text element is hidden in the UI. |

### Example

```xml
<workflow-form>
  <text label="Please fill in all required fields below."
        name="instructions" width="100%" />
  <text label="&lt;b&gt;Important:&lt;/b&gt; attach the signed document."
        name="warningText" width="100%" />
  <!-- Text loaded dynamically from the workflow context -->
  <text label="" name="dynamicMsg" data="statusMessage" width="100%" />
  <input label="Comments" name="comments" />
</workflow-form>
```

---

## Workflow TextArea field

Multi-line text field. Supports plain text or a rich HTML editor.

### Attributes

| Attribute     | Type    | Required | Default | Description |
|---------------|---------|----------|---------|-------------|
| `label`       | String  | Yes | — | Text shown as the field label in the UI. |
| `name`        | String  | Yes | — | Unique field identifier within the form. |
| `type`        | Enum    | No  | `text`  | `text` — plain text; `html` — rich-text HTML editor. |
| `value`       | String  | No  | — | Default content of the field. |
| `data`        | String  | No  | — | Context variable name used to load the initial value dynamically. |
| `width`       | String  | No  | — | HTML element width. Use percentage values for KCenter UI. |
| `height`      | String  | No  | — | HTML element height. |
| `placeholder` | String  | No  | — | Placeholder text shown when the field is empty. |
| `description` | String  | No  | — | Descriptive text for the field. |
| `readonly`    | Boolean | No  | `false` | When `true`, prevents modification from the UI. |
| `visible`     | Boolean | No  | `true`  | When `false`, the field is hidden in the UI. |

### Child elements

`<validator>`

### Example

```xml
<workflow-form>
  <textarea label="Description" name="description"
            placeholder="Enter any relevant notes here."
            height="150px" />
  <textarea label="Summary"     name="summary"
            type="html" height="200px" />
  <!-- Pre-filled from the workflow context -->
  <textarea label="Original request" name="originalRequest"
            data="requestDescription" readonly="true" height="100px" />
</workflow-form>
```

---

## Workflow Upload field

Allows the user to upload a document to OpenKM as part of the task. Supports creating a new document or updating an existing one.

### Attributes

| Attribute            | Type    | Required | Default  | Description |
|----------------------|---------|----------|----------|-------------|
| `label`              | String  | Yes | — | Text shown as the field label in the UI. |
| `name`               | String  | Yes | — | Unique field identifier within the form. |
| `type`               | Enum    | No  | `create` | `create` — uploads a new document; `update` — creates a new version of an existing document. |
| `folderPath`         | String  | No  | — | OpenKM path of the destination folder (for `type="create"`). |
| `folderUuid`         | String  | No  | — | UUID of the destination folder (for `type="create"`). |
| `documentName`       | String  | No  | — | Forces the name of the uploaded document. |
| `documentUuid`       | String  | No  | — | UUID of the document to replace (for `type="update"`). |
| `allowedExtensions`  | String  | No  | — | Semicolon-separated list of allowed file extensions (e.g. `pdf;png;docx`). |
| `multiple`           | Boolean | No  | `false`  | When `true`, allows uploading multiple files at once. |
| `data`               | String  | No  | — | Context variable name used to load upload parameters dynamically (e.g. `folderPath`, `folderUuid`). |
| `width`              | String  | No  | — | HTML element width. Use percentage values for KCenter UI. |
| `height`             | String  | No  | — | HTML element height. |
| `visible`            | Boolean | No  | `true`   | When `false`, the field is hidden in the UI. |

> **To create:** specify `folderPath` or `folderUuid`, and optionally `documentName`.
> **To update:** specify `documentUuid` and `type="update"`.
> **`multiple` is a static form-XML attribute only.** It controls whether the browse dialog accepts multiple files. The `Upload` bean used in Action nodes to pre-configure the destination (`setFolderUuid()`, `setFolderPath()`, `setType()`, `setDocumentUuid()`) has nothing to configure for it — this attribute has no programmatic equivalent.

### Child elements

`<validator>`

### Examples

**Upload new document to a fixed folder:**

```xml
<workflow-form>
  <upload name="signedContract" label="Upload signed contract"
          folderUuid="fca2d85e-0e01-418d-8699-c0dd0f8190da"
          allowedExtensions="pdf" />
</workflow-form>
```

**Update an existing document version:**

```xml
<workflow-form>
  <upload name="updatedDoc" label="Upload new version"
          type="update"
          documentUuid="e6a06309-c1cf-42be-98fd-7d7ed83ebda8" />
</workflow-form>
```

To prepare the `Upload` bean for `type="update"` programmatically (equivalent to `setFolderUuid()` for `type="create"`), use `setType("update")` and `setDocumentUuid()`:

```groovy
// In the Action node prior to the task:
import com.openkm.bean.form.*;

// Get the UUID of the document to be versioned (previously stored in context)
Input documentInput = (Input) context.get("documentUuid");

Upload upd = new Upload();
upd.setType("update");
upd.setDocumentUuid(documentInput.getValue());
context.put("documentUpdate", upd);
```

```xml
<upload label="Replace document" name="replaceDocument" data="documentUpdate" />
```

> As with `type="create"`, the context key used in `data=` should differ from the form field `name` to prevent the descriptor from being overwritten on submission (see the Upload naming convention note in the OKMFlow context variables reference).

**Dynamic destination (loaded from the workflow context):**

```xml
<workflow-form>
  <upload name="upload" label="Upload document" data="uploadParams" />
</workflow-form>
```

```groovy
// In the Action node prior to the task:
import com.openkm.bean.form.*;
Upload upd = new Upload();
upd.setFolderPath("/okm:root/contracts/2024");
context.put("uploadParams", upd);
```

---

## Workflow VerticalPanel field

Container that stacks its children vertically. Used to group fields or build multi-column layouts together with `<hpanel>`.

### Attributes

| Attribute | Type    | Required | Default | Description |
|-----------|---------|----------|---------|-------------|
| `name`    | String  | Yes | — | Unique container identifier within the form. |
| `width`   | String  | No  | — | Container width. Use percentage values for KCenter UI. |
| `height`  | String  | No  | — | Container height. |
| `visible` | Boolean | No  | `true`  | When `false`, the panel and all its children are hidden. |

### Child elements

All field types: `<input>`, `<checkbox>`, `<select>`, `<suggestbox>`, `<textarea>`, `<text>`, `<separator>`, `<button>`, `<upload>`, `<download>`, `<vpanel>`, `<hpanel>`.

### Example

```xml
<workflow-form>
  <vpanel name="leftCol" width="50%">
    <input label="First name" name="firstName" type="text" />
    <input label="Last name"  name="lastName"  type="text" />
  </vpanel>
  <vpanel name="rightCol" width="50%">
    <input label="Start date" name="startDate" type="date" />
    <input label="End date"   name="endDate"   type="date" />
  </vpanel>
</workflow-form>
```

---

## Workflow HorizontalPanel field

Container that places its children in a row. Combined with `<vpanel>`, it allows creating grid-like layouts.

### Attributes

| Attribute | Type    | Required | Default | Description |
|-----------|---------|----------|---------|-------------|
| `name`    | String  | Yes | — | Unique container identifier within the form. |
| `width`   | String  | No  | — | Container width. Use percentage values for KCenter UI. |
| `height`  | String  | No  | — | Container height. |
| `visible` | Boolean | No  | `true`  | When `false`, the panel and all its children are hidden. |

### Child elements

All field types: `<input>`, `<checkbox>`, `<select>`, `<suggestbox>`, `<textarea>`, `<text>`, `<separator>`, `<button>`, `<upload>`, `<download>`, `<vpanel>`, `<hpanel>`.

### Example

```xml
<workflow-form>
  <hpanel name="row1">
    <input label="Invoice number" name="invoiceNumber" type="text" width="50%" />
    <input label="Amount"         name="amount"        type="text" width="50%" />
  </hpanel>
  <hpanel name="row2">
    <input label="Date"           name="invoiceDate"   type="date" width="50%" />
    <select label="Status"        name="status"        type="simple" width="50%">
      <option label="Pending"  value="pending" selected="true" />
      <option label="Approved" value="approved" />
      <option label="Rejected" value="rejected" />
    </select>
  </hpanel>
  <button name="submit" label="Submit" transition="submit" color="primary" />
</workflow-form>
```

---

## Workflow Option element

Child element of `<select>`. Defines a selectable option.

### Supported parent fields

`<select>`

### Attributes

| Attribute     | Type    | Required | Default | Description |
|---------------|---------|----------|---------|-------------|
| `label`       | String  | Yes | — | Text displayed to the user for this option. |
| `value`       | String  | Yes | — | Stored identifier. Must be unique within the field. |
| `parentValue` | String  | No  | — | When the `<select>` uses `parentElement`, ties this option to a specific value of the parent field. |
| `selected`    | Boolean | No  | `false` | Pre-selects this option when the form loads. |
| `cssClass`    | String  | No  | — | Custom CSS class applied to this option's element. |

### Example

```xml
<!-- Flat options with a default selection -->
<select label="Decision" name="decision" type="simple">
  <option label="Approve" value="approve" />
  <option label="Reject"  value="reject" selected="true" />
  <option label="Defer"   value="defer" />
</select>

<!-- Hierarchical options -->
<select label="Category"    name="category"    type="simple">
  <option value="contract" label="Contract" />
  <option value="invoice"  label="Invoice" />
</select>

<select label="Sub-category" name="subcategory"
        type="simple" parentElement="category">
  <option value="service"  label="Service contract"  parentValue="contract" />
  <option value="purchase" label="Purchase contract" parentValue="contract" />
  <option value="supplier" label="Supplier invoice"  parentValue="invoice" />
  <option value="customer" label="Customer invoice"  parentValue="invoice" />
</select>
```

---

## Workflow Validator element

Child element that applies a validation rule to the field when the form is submitted.

### Supported parent fields

`<input>`, `<checkbox>`, `<select>`, `<suggestbox>`, `<textarea>`, `<upload>`, `<download>`

### Attributes

| Attribute   | Type   | Required | Description |
|-------------|--------|----------|-------------|
| `type`      | String | Yes | Validator type (see table below). |
| `parameter` | String | No  | Additional configuration value (e.g. length limit or regex pattern). |

### Built-in validator types

| Type       | Parameter    | Description |
|------------|--------------|-------------|
| `req`      | —            | Field is required (must not be empty). |
| `alpha`    | —            | Value must contain alphabetic characters only. |
| `alphanum` | —            | Value must contain alphanumeric characters only. |
| `dec`      | —            | Value must be a valid decimal number. |
| `num`      | —            | Value must be a valid integer. |
| `email`    | —            | Value must be a valid email address. |
| `url`      | —            | Value must be a valid URL. |
| `maxlen`   | max length   | Value length must not exceed the given number of characters. |
| `minlen`   | min length   | Value length must be at least the given number of characters. |
| `lt`       | threshold    | Numeric value must be less than the parameter. |
| `gt`       | threshold    | Numeric value must be greater than the parameter. |
| `min`      | minimum      | Numeric value must be greater than or equal to the parameter. |
| `max`      | maximum      | Numeric value must be less than or equal to the parameter. |
| `regexp`   | pattern      | Value must match the given regular expression. |
| `plugin`   | class name   | Delegates validation to a custom `FormValidator` plugin class. |

### Example

```xml
<input label="Amount" name="amount" type="text">
  <validator type="req" />
  <validator type="dec" />
  <validator type="gt"  parameter="0" />
  <validator type="max" parameter="999999" />
</input>

<input label="Email" name="email" type="text">
  <validator type="req" />
  <validator type="email" />
</input>

<input label="Code" name="code" type="text">
  <validator type="regexp" parameter="[A-Z]{2}[0-9]{4}" />
</input>

<input label="Lowercase notes" name="notes" type="text">
  <validator type="regexp" parameter="[a-z]+" />
</input>

<input label="Notes (plugin)" name="customField" type="text">
  <validator type="plugin" parameter="com.example.plugin.MyFieldValidator" />
</input>
```
