User Defined Fields (UDF)

You can create your own fields under the Clients, Users, Project, and Suppliers modules. In the Projects module, you can find the extra fields in the Overview tab, beneath the map.

User defined fields (UDF) can be only created in the API Admin. Normally, your Kompass Champion should have access on the API Admin.

To create your fields, you will initially have to create a Project UDF schema. Head to "Client/ User/ Project/ Supplier UDF Schema" (1) and click "Add UDF schema" (2).

Add a name and then you'll have to set the schema.

Please note that once you have create your UDF schema, you will have to allocate it to your org. Head to your org page and select the schema at the relevant module.

Understanding the Schema Definition


You can see the basic structure of a UDF schema below:

{
  "type": "object",
  "properties": {
    "field_name": {
      "type": "string",
      "label": "Field Label",
      "default": null,
      "x-order": 1
    }
  },
  "required": [
    "field_name"
  ]
}

Field Properties

As seen above, you can use certain properties under the field_name.

Property Description Example
type   Field data type (see Field Types) "string"  , ["string", "null"]  
label   Display label shown in the UI "Company Name"  
default   Default value when field is empty null  , ""  , 0  , false  
enum   List of allowed values (creates dropdown) ["Active", "Inactive", "Pending"]  

There are additional custom extensions available from your fields (x- prefixed)

Property Description Applies To Example
x-order   Display order (lowest first) All fields 1  , 2  , 3  
x-widget   Override default widget (see Widgets) Entity reference fields "date"  , "client"  
x-depends-on   Parent field (clears when parent changes) Required: contact  , quote_item  , task   "client_id"  , "project_id"  
x-module   Module context for tags Required: tags   widget "clients"  , "projects"  
x-multi-line   Enable textarea mode String fields (required if x-rows   is set) true  , false  
x-rows   Number of textarea rows String fields (requires x-multi-line: true  ) 3  , 5  , 10  

Field Types


1. Text Field

This is a standard string field used for capturing text, such as notes or simple descriptions. You can allow it to be left empty by setting the type    to ["string", "null"]   .

  • Example Use: A "Plot" description.
  • Code Definition:

    JSON

"plot": {
  "type": "string",
  "label": "Plot",
  "x-order": 1,
  "default": null
}
  • Code Definition (with null allowed):

    JSON

"plot": {
  "type": [
    "string",
    "null"
  ],
  "label": "Plot",
  "x-order": 1,
  "default": null
}

2. Checkbox (Yes/No)

This is a boolean field that appears as a simple checkbox. It's ideal for tracking true/false or yes/no information.

  • Example Use: A "RAMS Sent" checkbox.
  • Code Definition:

    JSON

"rams": {
  "type": "boolean",
  "label": "RAMS Sent",
  "default": false
}

3. Dropdown List

This field allows users to select a single option from a predefined list. Use the enum    property to list the available options. Including null    in the enum    list makes the field optional.

  • Example Use: A "State Area" field.
  • Code Definition:

    JSON

"section": {
  "enum": [
    "Central",
    "East",
    "North",
    "South",
    "West",
    null
  ],
  "type": [
    "string",
    "null"
  ],
  "label": "State Area",
  "x-order": 2,
  "default": null
}

4. Date Field

This field provides a calendar picker. By setting the format    to date   , you ensure the input is correctly handled as a date.

  • Example Use: An "Archive Date".
  • Code Definition:

    JSON

"archive_date": {
  "type": [
    "string",
    "null"
  ],
  "format": "date",
  "label": "Archive Date",
  "x-order": 3,
  "x-widget": "date",
  "default": null
}

5. Number Field

This field is used for entering numerical data only. You can set a default    value, such as 0   .

  • Example Use: An "Acres" field.
  • Code Definition:

    JSON

"acres": {
  "type": [
    "number",
    "null"
  ],
  "label": "Acres",
  "x-order": 4,
  "default": 0
}

Making Fields Required/Optional

Required Fields

Fields are required by default. To make a field mandatory:

{
  "type": "object",
  "properties": {
    "company_name": {
      "type": "string",
      "label": "Company Name"
    }
  },
  "required": [
    "company_name"
  ]
}

Optional Fields (Nullable)

To allow null values, use an array type with "null"  :

{
  "type": [
    "string",
    "null"
  ],
  "label": "Optional Field",
  "default": null
}

Examples:

// Optional string
{
  "type": [
    "string",
    "null"
  ],
  "label": "Middle Name",
  "default": null
}

// Optional integer
{
  "type": [
    "integer",
    "null"
  ],
  "label": "Employee Number",
  "default": null
}

// Optional number
{
  "type": [
    "number",
    "null"
  ],
  "label": "Discount Rate",
  "default": null
}

UI Behaviour:

  • Fields with "null"   in type array will show a clear button (×) when in edit mode
  • Clearing the field sets the value to null  
  • Empty strings in nullable fields are automatically converted to null  

Widgets

Widgets determine how fields are rendered in the UI. Most widgets are automatically selected based on the field type. The x-widget   property is only used to specify special selector widgets.

Automatic Widget Selection

The widget is automatically determined by the field type:

Type Condition Rendered As UI Component
string   Has enum   Dropdown KSelect
string   No enum   Text field KTextField
integer   - Number field KTextField
number   - Number field KTextField
boolean   - Checkbox KCheckbox

String Field Options:

  • x-multi-line  : Enable textarea mode (true  /false  ). If true   and x-rows   is not specified, defaults to 1 row.
  • x-rows  : Number of rows for textarea (integer, requires x-multi-line: true  )

Examples:

// Simple text field
{
  "type": "string",
  "label": "Name"
}

// Textarea field
{
  "type": "string",
  "label": "Description",
  "x-multi-line": true,
  "x-rows": 5
}

// Dropdown (enum)
{
  "type": "string",
  "label": "Status",
  "enum": [
    "Active",
    "Inactive"
  ]
}

// Number field
{
  "type": "integer",
  "label": "Count"
}

// Checkbox
{
  "type": "boolean",
  "label": "Enabled"
}

Special Selector Widgets (via x-widget)

Use x-widget   to specify special selector components for entity references. These must be explicitly set and require integer   or array   types.

Date Widget

{
  "type": [
    "string",
    "null"
  ],
  "label": "Due Date",
  "x-widget": "date",
  "default": null
}

Divider Widget

Renders a horizontal divider line that spans the full width. Useful for visually grouping fields.

{
  "type": "null",
  "x-widget": "divider",
  "default": null
}

With text label:

{
  "type": "null",
  "x-widget": "divider",
  "label": "Personal Information",
  "default": null
}

Note: Divider widgets don't store data. Use the label   property to display text in the middle of the divider line.

Client Widget

{
  "type": [
    "integer",
    "null"
  ],
  "label": "Client",
  "x-widget": "client",
  "default": null
}

Contact Widget

Requires: x-depends-on   (field containing client ID)

{
  "type": [
    "integer",
    "null"
  ],
  "label": "Contact",
  "x-widget": "contact",
  "x-depends-on": "client_id",
  "default": null
}

Filters contacts by the selected client.

Project Widget

{
  "type": [
    "integer",
    "null"
  ],
  "label": "Project",
  "x-widget": "project",
  "default": null
}

Quote Item Widget

Requires: x-depends-on   (field containing project ID)

{
  "type": [
    "integer",
    "null"
  ],
  "label": "Quote Item",
  "x-widget": "quote_item",
  "x-depends-on": "project_id",
  "default": null
}

Filters quote items by the selected project.

Task Widget

Requires: x-depends-on   (field containing project ID or quote item ID)

{
  "type": [
    "integer",
    "null"
  ],
  "label": "Task",
  "x-widget": "task",
  "x-depends-on": "project_id",
  "default": null
}

Filters tasks by the selected project or quote item. The x-depends-on   value can be either "project_id"   or "quote_item_id"  .

Supplier Widget

{
  "type": [
    "integer",
    "null"
  ],
  "label": "Supplier",
  "x-widget": "supplier",
  "default": null
}

User Widget

{
  "type": [
    "integer",
    "null"
  ],
  "label": "Assigned To",
  "x-widget": "user",
  "default": null
}

Tags Widget

{
  "type": [
    "array",
    "null"
  ],
  "label": "Tags",
  "x-widget": "tags",
  "x-module": "clients",
  "default": null
}

Options:

  • x-module  : Module context for tags (e.g., "clients"  , "projects"  , "tasks"  )

Field Dependencies

Fields can depend on other fields using x-depends-on  . When the parent field changes, dependent fields are automatically cleared.

Example: Client → Contact

{
  "type": "object",
  "properties": {
    "client_id": {
      "type": [
        "integer",
        "null"
      ],
      "label": "Client",
      "x-widget": "client",
      "x-order": 1,
      "default": null
    },
    "contact_id": {
      "type": [
        "integer",
        "null"
      ],
      "label": "Contact",
      "x-widget": "contact",
      "x-depends-on": "client_id",
      "x-order": 2,
      "default": null
    }
  }
}

Behaviour:

  • Contact selector is filtered by selected client
  • When client changes, contact field is cleared to null  
  • Dependency chains are supported (A → B → C)

Example: Project → Quote Item → Task

{
  "type": "object",
  "properties": {
    "project_id": {
      "type": [
        "integer",
        "null"
      ],
      "label": "Project",
      "x-widget": "project",
      "x-order": 1,
      "default": null
    },
    "quote_item_id": {
      "type": [
        "integer",
        "null"
      ],
      "label": "Quote Item",
      "x-widget": "quote_item",
      "x-depends-on": "project_id",
      "x-order": 2,
      "default": null
    },
    "task_id": {
      "type": [
        "integer",
        "null"
      ],
      "label": "Task",
      "x-widget": "task",
      "x-depends-on": "quote_item_id",
      "x-order": 3,
      "default": null
    }
  }
}

Complete Example

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "label": "Status",
      "enum": [
        "New",
        "In Progress",
        "Completed",
        "On Hold"
      ],
      "default": "New",
      "x-order": 1
    },
    "client_id": {
      "type": [
        "integer",
        "null"
      ],
      "label": "Related Client",
      "x-widget": "client",
      "x-order": 2,
      "default": null
    },
    "contact_id": {
      "type": [
        "integer",
        "null"
      ],
      "label": "Primary Contact",
      "x-widget": "contact",
      "x-depends-on": "client_id",
      "x-order": 3,
      "default": null
    },
    "priority": {
      "type": "integer",
      "label": "Priority Level",
      "default": 3,
      "x-order": 4
    },
    "budget": {
      "type": [
        "number",
        "null"
      ],
      "label": "Budget",
      "default": null,
      "x-order": 5
    },
    "due_date": {
      "type": [
        "string",
        "null"
      ],
      "label": "Due Date",
      "x-widget": "date",
      "x-order": 6,
      "default": null
    },
    "is_billable": {
      "type": "boolean",
      "label": "Billable",
      "default": true,
      "x-order": 7
    },
    "notes": {
      "type": [
        "string",
        "null"
      ],
      "label": "Notes",
      "x-multi-line": true,
      "x-rows": 5,
      "x-order": 8,
      "default": null
    },
    "assigned_to": {
      "type": [
        "integer",
        "null"
      ],
      "label": "Assigned To",
      "x-widget": "user",
      "x-order": 9,
      "default": null
    },
    "tags": {
      "type": [
        "array",
        "null"
      ],
      "label": "Tags",
      "x-widget": "tags",
      "x-module": "projects",
      "x-order": 10,
      "default": null
    }
  },
  "required": [
    "status",
    "priority",
    "is_billable"
  ]
}

Validation

Backend Validation

All UDF data is validated against the schema on save:

  • Type checking (string, integer, number, boolean)
  • Required field validation
  • Enum value validation
  • Field dependencies are checked

Frontend Validation

The UI provides real-time validation:

  • Required fields show error if empty
  • Number fields validate numeric input
  • Integer fields validate integer input
  • Nullable fields can be cleared

Validation Errors

Validation errors are returned in the format:

{
  "udf": {
    "field_name": "Error message"
  }
}

Best Practices

  1. Always specify x-order: Ensures consistent field ordering
  2. Use null for optional fields: Include "null"   in type array
  3. Set sensible defaults: Provide default values for all fields
  4. Use dependencies wisely: Create logical field relationships
  5. Keep labels concise: Use clear, short labels (2-4 words)
  6. Document custom widgets: Use comments to explain complex schemas
  7. Test validation: Verify required/optional field behaviour
  8. Consider field width: Fields are displayed in 3-column layout

Common Patterns

Optional Reference Field

{
  "type": [
    "integer",
    "null"
  ],
  "label": "Related Entity",
  "x-widget": "client",
  "default": null
}

Required Dropdown

{
  "type": "string",
  "label": "Category",
  "enum": [
    "A",
    "B",
    "C"
  ],
  "default": "A"
}

Dependent Selectors

{
  "parent_id": {
    "type": [
      "integer",
      "null"
    ],
    "x-widget": "client",
    "x-order": 1
  },
  "child_id": {
    "type": [
      "integer",
      "null"
    ],
    "x-widget": "contact",
    "x-depends-on": "parent_id",
    "x-order": 2
  }
}

Large Text Field

{
  "type": [
    "string",
    "null"
  ],
  "label": "Description",
  "x-multi-line": true,
  "x-rows": 8,
  "default": null
}
Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.

Still need help? Contact Us Contact Us