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 Admin site. Normally, your Kompass Champion should have access on the Admin site.

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",
          "null"
        ],
      "label": "Field Label",
      "default": null,
      "x-order": 1
    }
  }
}

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"
    }
  }
}

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