Karma

Karma

  • Docs
  • Forms
  • FAQ
  • Changelog

›Forms

Forms

  • Karma Forms
  • Karma Form Controls

Karma Form Controls

k5-repeat-section

since v2.8.21

  • Option removeLabel to hide the remove button
{
  "type": "k5-repeat-section",
  "templateOptions": {
    "removeLabel": false
  }
}

k5-collapse

since v2.8.21

  • renaming template option uncollapsedText to expandedText
  • adding template options collapsedIconClass and expandedIconClass (using font-awesome classes, see defaults in example)
{
  "type": "k5-collapse",
    "templateOptions": {
      "collapsedText": "",
      "expandedText": "",
      "collapsedIconClass": "fa-square-o",
      "expandedIconClass": "fa-check-square-o"
    }
}

k5-select

since v2.8.18

  • new matchExpression option to override rendering of selected items
  • new dal async property to allow async/typeahead like search behavior
  • new dal $take option to define how many choices should be loaded
  • the model may contain a sibling property with initial enhanced objects for already selected options: _<model key>_options; this can be populate using the model script: model["_child-roles_options"] = await IDVAult.globalQuery(null, 'roles', {$include: model["child-roles"]}) using the below dal config
  • if a $partition is included in the result, it is shown before each match and choice; to ensure $partition is added to each result set the server dal config option loadDefaultProperties to true (see below)
  • (since v2.8.19) forms(k5-select): when not defining matchExpression or labelExpression fallback to labelProp

field.json

{
  "type": "k5-select",
  "key": "child-roles",
  "templateOptions": {
    "multiple": true,
    "valueProp": "entryDN",
    "labelExpression": "$item.name",
    "descriptionExpression": "$item.description",
    "matchExpression": "{{$item.name}} <small>{{_.truncate($item.description, {length: 15})}}</small>",
    "dal": {
      "key": "roles",
      "async": true,
      "options": {
        "$take": 5
      }
    }
  }
}

model.json

{
  "child-roles": [
    "cn=Finance,cn=Level30,cn=RoleDefs,cn=RoleConfig,cn=AppConfig,cn=User Application Driver,cn=driverset,o=system",
    "cn=Level10,cn=Level10,cn=RoleDefs,cn=RoleConfig,cn=AppConfig,cn=User Application Driver,cn=driverset,o=system"
  ],
  "_child-roles_options": [
    {
      "entryDN":"cn=Finance,cn=Level30,cn=RoleDefs,cn=RoleConfig,cn=AppConfig,cn=User Application Driver,cn=driverset,o=system",
      "nrfLocalizedDescrs":{
        "en":"Finance Department"
      },
      "nrfLocalizedNames":{
        "en":"Finance"
      },
      "cn":"Finance",
      "entryUUID":"60914df0-5edf-0941-b192-60914df05edf",
      "$id":"60914df0-5edf-0941-b192-60914df05edf",
      "$name":"Finance",
      "$partition":{
        "id":"k5",
        "ui":{
          "label":"Kenoxa",
          "logo":"logo.png",
          "icon":"Karma_symbol_blau.png"
        }
      },
      "$type":"role",
      "nrfStatus":"50",
      "nrfRoleLevel":"30",
      "nrfRoleCategoryKey":[
        "default",
        "favorites"
      ],
      "name":"Finance",
      "description":"Finance Department"
    },
    {
      "entryDN":"cn=Level10,cn=Level10,cn=RoleDefs,cn=RoleConfig,cn=AppConfig,cn=User Application Driver,cn=driverset,o=system",
      "nrfLocalizedDescrs":{
        "en":"Level10, Permission Role"
      },
      "nrfLocalizedNames":{
        "en":"Level10"
      },
      "cn":"Level10",
      "entryUUID":"03ebaf0b-23d3-c740-9e81-03ebaf0b23d3",
      "$id":"03ebaf0b-23d3-c740-9e81-03ebaf0b23d3",
      "$name":"Level10",
      "$partition":{
        "id":"k5",
        "ui":{
          "label":"Kenoxa",
          "logo":"logo.png",
          "icon":"Karma_symbol_blau.png"
        }
      },
      "$type":"role",
      "nrfStatus":"50",
      "nrfRoleLevel":"10",
      "name":"Level10",
      "description":"Level10, Permission Role"
    }
  ]
}

html

since v2.8.8

This control allows to render an html expression. The key property is optional and may access a property within the model.

{
  "type": "html",
  "key": "isNew",
  "templateOptions": {
    "label": "Is New",
    "expression": "<i class='fa fa-fw fa-{{model ? 'check-square-o' : 'square-o'}}'></i>"
  }
}

button

Renders a <button />. The following templateOptions are supported:

  • text (deprecated since v2.11.4, use label)
  • label (since v2.11.4): to display
  • icon (optional): font-awesome icon without fa- prefix
  • btnType: the button style (one of: default, primary, success, info, warning, danger or link)
  • onClick: expression to evaluate, the model can be accessed as model
  • className: additional css class names applied to the wrapper div

Since v2.11.4 these options maybe changed via expressionProperties.

{
  "type": "button",
  "templateOptions": {
    "text": "Accept",
    "btnType": "primary",
    "icon": "check",
    "onClick": "model.accepted = !model.accepted"
  },
  "expressionProperties": {
    "templateOptions.icon": "model.accepted ? 'check-square' : 'square'"
  }
}

intro

since v2.20.0

Powered by intro.js

Renders a link to start a intro.

Example

{
  "type": "intro",
  "templateOptions": {
    "steps": [
      {
        "element": "[data-form-field=\"user__password\"]",
        "intro": "{{$index}} step"
      },
      {
        "element": "[data-form-field=\"ctrl.form_input_cn_2\"]",
        "intro": "Second tooltip",
        "position": "right"
      }
    ]
  }
}

Translation example (config/i18n/formly/[locale].yaml)

types:
  intro:
    label: Hilfe
    # Next button label in tooltip box
    nextLabel: 'Weiter &rarr;'
    # Previous button label in tooltip box
    prevLabel: '&larr; Zurück'
    # Skip button label in tooltip box
    skipLabel: 'Überspringen'
    # Done button label in tooltip box
    doneLabel: 'Fertig'
    # Hint button label
    hintButtonLabel: 'Verstanden'
    Second tooltip: 'Zweiter Tooltip'

Template Options

Interpolated Properties

These properties are interpolated and then translated. If no translation is found the value is used as is.

  • 'nextLabel': 'Next &rarr;' - Next button label in tooltip box
  • 'prevLabel': '&larr; Back' - Previous button label in tooltip box
  • 'skipLabel': 'Skip' - Skip button label in tooltip box
  • 'doneLabel': 'Done' - Done button label in tooltip box
  • 'hintButtonLabel': 'Got it' - Hint button label

Value Properties

  • 'label': 'label' - translated via types.intro.label in config/i18n/formly/[locale].yaml
  • 'btnType': 'link' - button type
  • 'btnClass': undefined - additional css classes
  • 'icon': 'question-circle' - font-awesome icon without fa- prefix
  • 'steps': [] - steps to render (see below for options)
  • 'hidePrev': false - Hide previous button in the first step? Otherwise, it will be disabled button.
  • 'hideNext': false - Hide next button in the last step? Otherwise, it will be disabled button.
  • 'tooltipPosition': 'auto' - Default tooltip box position, top, left, right, bottom, bottom-left-aligned (same as bottom), bottom-middle-aligned, bottom-right-aligned or auto (to detect the position of element and assign the correct position automatically). Default is auto
  • 'tooltipClass': '' - Next CSS class for tooltip boxes
  • 'highlightClass': '' - CSS class that is added to the helperLayer
  • 'exitOnEsc': true - Close introduction when pressing Escape button?
  • 'exitOnOverlayClick': true - Close introduction when clicking on overlay layer?
  • 'showStepNumbers': true - Show step numbers in introduction?
  • 'keyboardNavigation': true - Let user use keyboard to navigate the tour?
  • 'showButtons': true - Show tour control buttons?
  • 'showBullets': true - Show tour bullets?
  • 'showProgress': false - Show tour progress?
  • 'scrollToElement': true - Scroll to highlighted element?
  • 'scrollTo': 'element' - Should we scroll the tooltip or target element? Options are: element or tooltip
  • 'scrollPadding': 30 - Padding to add after scrolling when element is not in the viewport (in pixels)
  • 'overlayOpacity': 0.8 - Set the overlay opacity
  • 'positionPrecedence': ["bottom", "top", "right", "left"] - Precedence of positions, when auto is enabled
  • 'disableInteraction': false - Disable an interaction with element?
  • 'helperElementPadding': 10 - Set how much padding to be used around helper element
  • 'hintPosition': 'top-middle' - Default hint position
  • 'hintAnimation': true - Adding animation to hints?
  • 'buttonClass': "introjs-button - additional classes to put on the buttons

Step Properties

  • 'intro' - interpolated text (see above)
  • 'element' - css selector for the element; each form element its id reflected in the data-form-field attribute, this allows to use the id as an element selector: [data-form-field="field_id"]
  • 'tooltipClass': '' - Optionally define a CSS class for tooltip
  • 'highlightClass': '' - Optionally append a CSS class to the helperLayer
  • 'position': 'auto' - Optionally define the position of tooltip, top, left, right, bottom, bottom-left-aligned (same as bottom), bottom-middle-aligned, bottom-right-aligned or auto (to detect the position of element and assign the correct position automatically). Default is auto
  • 'scrollTo': 'element' - Should we scroll the tooltip or target element? Options are: element or tooltip
  • 'disableInteraction': false - Disable an interaction with element?

unique-input

since v2.8.10

This form control allows to check if an input field contains a unique value by performing a dal query and evaluating the result.

Example field configuration:

{
  "type": "unique-input",
  "key": "cn",
  "templateOptions": {
    "label": "Login Name",
    "dal": {
      "key": "users-by-cn",
      "attribute": "cn"
    }
  },
  "asyncValidators": {
    "unique": {
      "message": "'This Login Name is not unique.' | formlyTranslate"
    }
  }
},

Example dal query (local.yaml):

# ...
dal:
  'users-by-cn':
    type: 'ldap:list'
    authz: 'user'
    options:
      base: '<%= users.base %>'
      scope: '<%= users.scope %>'
      filter: '<%= users.filter %>'
      attributes: cn
      query:
        'cn!': 'cn'

It is possible to use other model values to populate the queryOptions (since v2.14.4):

[
  {
    "className": "row",
    "fieldGroup": [
      {
        "type": "input",
        "key": "department",
        "className": "col-sm-4",
        "templateOptions": { "label": "Department" }
      },
      {
        "type": "input",
        "key": "prefix",
        "className": "col-sm-4",
        "templateOptions": { "required": true, "label": "Prefix" }
      },
      {
        "type": "unique-input",
        "key": "suffix",
        "className": "col-sm-4",
        "templateOptions": {
          "label": "Suffix",
          "required": true,
          "dal": { "key": "users-by-cn" }
        },
        "expressionProperties": {
          "templateOptions.dal.queryOptions.cn": "model.prefix + '-' + model.suffix",
          "templateOptions.dal.queryOptions.department": "model.department"
        },
        "asyncValidators": {
          "unique": { "message": "'Es existiert bereits ein Benutzer mit diesem Namen.'" }
        }
      }
    ]
  }
]

k5-paged-list

since v2.13.0

Allows to display a paginated DAL list. This is especially useful in combination with a search field:

[
  {
    "type": "input",
    "key": "q",
    "className": "col-sm-6",
    "templateOptions": {
      "placeholder": "Search ..."
    },
    "modelOptions": {
      "debounce": { "default": 350, "blur": 0, "*": 150 }
    }
  },
  {
    "type": "k5-paged-list",
    "className": "col-sm-6",
    "templateOptions": {
      "options": [],
      "dal": {
        "key": "accounts-search"
      },
      "fields": [{
        "type": "html",
        "templateOptions": {
          "expression": "{{model.givenName}} {{model.sn}}"
        }
      }]
    },
    "expressionProperties": {
      "templateOptions.dal.options.$q": "model.q"
    }
  }
]

Corresponding DAL definition:

dal:
  'accounts-search':
    type: 'ldap:list'
    # admin, user (default) or guest
    authz: 'user'
    options:
      base: '<%= accounts.base %>'
      scope: '<%= accounts.scope %>'
      filter: '<%= accounts.filter %>'
      attributes:
        entryDN cn givenName sn
      qAttributes:
        cn givenName sn
      useServerSideSort: true
      sortBy: cn
      take: 10

json-tree

since v2.8.8

This control allows to render an json object as a tree. The key property is optional and may access a property within the model.

templateOptions:

  • rootName: This is an optional attribute that sets the title displayed at the root node. This is useful when you are showing sub-portions of an object or want the object root node to have a different string than the key or 'Model'.
  • start-expanded: This is an optional attribute that designates if the tree's root should display as expanded initially.
{
  "type": "json-tree",
  "key": "treeDataProperty",
  "templateOptions": {
    "rootName": "Data Tree",
  }
}

since v2.8.11

  • color and indention matching global style
  • used model values are customizable

Example:

[{
  "type": "json-tree",
  "key": "someKey",
  "customize": "_.map(model, 'nested.model.path')"
}, {
  "type": "k5-merge-ui",
  "templateOptions": {
    "fields": [{
      "key": "urmAffiliations",
      "label": "Category Data",
      "isArray": true,
      "rootName": "Category Data",
      "jsonTreeCustomize": "_.map(model, 'affiliation.model')"
    }]
  }
}]

since v2.8.10

The json-tree from control now allows to customize the input object via an expression.

The following example shows how to display only a child property of the actual object.

Example field configuration:

{
  "type": "json-tree",
  "key": "myObject",
  "templateOptions": {
    "label": "My Object",
    "customize": "_.map(model, 'data.model')"
  }
}

Let's assume myObject is defined as follows:

[
  {
    id: 123,
    data: {
      foo: 'bar',
      model: {
        name: 'baz',
        limit: 5,
        isGreat: true
      }
    },
    metadata: {
      createdAt: '20170105121314Z'
    }
  },
  {
    id: 124,
    data: {
      foo: 'baz',
      model: {
        name: 'foo',
        limit: 30,
        isGreat: false
      }
    },
    metadata: {
      createdAt: '20170105121314Z'
    }
  }
]

json-tree would display the object like this:

[
  {
    name: 'baz',
    limit: 5,
    isGreat: true
  },
  {
    name: 'foo',
    limit: 30,
    isGreat: false
  }
]

dal-input

since v2.7.1

Karmas form controller dal-input can be used to fetch attributes using a DAL query and store the corresponding value directly into a text input field. The following is a example for a form definition that automatically fills first and last name as the user types a cn:

[{
  key: 'cn',
  type: 'input',
  className: 'col-sm-6',
  templateOptions: {
    label: 'CN',
    placeholder: 'Common Name',
    required: true
  }
}, {
  key: 'firstName',
  type: 'dal-input',
  className: 'col-sm-6',
  templateOptions: {
    label: 'First Name',
    placeholder: 'First Name',
    required: false,
    disabled: true,
    valueProp: 'givenName',
    dal: {
      key: 'user-by-cn'
    }
  },
  expressionProperties: {
    'templateOptions.dal.options.queryCN': 'model.cn'
  }
}, {
  key: 'lastName',
  type: 'dal-input',
  className: 'col-sm-6',
  templateOptions: {
    label: 'Last Name',
    placeholder: 'Last Name',
    required: false,
    disabled: true,
    valueProp: 'sn',
    dal: {
      key: 'user-by-cn'
    }
  },
  expressionProperties: {
    'templateOptions.dal.options.queryCN': 'model.cn'
  }
}]

The following configuration (local.yaml) shows the corresponding DAL entry.

dal:
  # ...
  'user-by-cn':
    type: 'ldap:entry'
    # admin, user (default) or guest
    authz: 'user'
    options:
      base: '<%= users.base %>'
      scope: 'sub'
      filter: '<%= users.filter %>'
      attributes: 'cn givenName sn'
      requireUnique: false
      query:
        queryCN: cn

k5-tabset

k5-tabset is a simple form control to organize form inputs in tabs. It supports 3 templateOptions:

  • fields: an array of elements containing a tab with a title and contents
  • justified: if false the tabs will only use the horizontal space they need to display the title. If true, the tabs will use the whole width of the page. Default is false.
  • vertical: if true tabs will be displayed vertically, if false tabs will be displayed horizontally. Default is false.

The following shows a sample configuration:

[
  {
    "type": "k5-tabset",
    "templateOptions": {
      "justified": false,
      "vertical": false,
      "fields": [
        {
          "templateOptions": {
            "title": "Personal Information",
            "fields": [
              {
                "className": "row",
                "fieldGroup": [
                  {
                    "type": "input",
                    "key": "givenName",
                    "className": "col-xs-12 col-sm-6",
                    "templateOptions": {
                      "label": "Given Name"
                    }
                  }, {
                    "type": "input",
                    "key": "surname",
                    "className": "col-xs-12 col-sm-6",
                    "templateOptions": {
                      "label": "Surname"
                    }
                  }
                ]
              }
            ]
          }
        },
        {
          "templateOptions": {
            "title": "Communication",
            "fields": [
              {
                "className": "row",
                "fieldGroup": [
                  {
                    "type": "input",
                    "key": "email",
                    "className": "col-xs-12 col-sm-6",
                    "templateOptions": {
                      "type": "email",
                      "label": "Email"
                    }
                  },
                  {
                    "type": "input",
                    "key": "phone",
                    "className": "col-xs-12 col-sm-6",
                    "templateOptions": {
                      "label": "Phone"
                    }
                  }
                ]
              }
            ]
          }
        }
      ]
    }
  }
]

wizard

The wizard allows you to define multi-step forms while conditionally showing, hiding or skipping steps.

It supports these templateOptions:

  • navigationMode (default: false):
    • if not set or set to false the next step is activated if the current step canExitExpression returns true
    • if set to true next and previous buttons are displayed which allow to change the active step
  • onFinishExpression : an expression to evaluate once the last step is completed
  • steps: an array of steps

Each step can have the following properties:

  • title: to show in step overview
  • description: to render as <h3 /> before the step fields
  • disabledExpression: determines if this step is disable and therefore hidden
  • canEnterExpression: determines if this step can be activated
  • onEnterExpression: evaluated once this step is activated
  • canExitExpression: determines if the next step should be activated
  • onExitExpression: evaluated once this step is deactivated
  • fields: the step content as an array of fields

Within each expression property the model can be accessed as model.

The following shows a sample configuration:

[
  {
    "type": "wizard",
    "templateOptions": {
      "navigationMode": true,
      "steps": [
        {
          "title": "Personal Information",
          "canExitExpression": "!!model.type",
          "fields": [
            {
              "type": "radio",
              "key": "type",
              "templateOptions": {
                "label": "User Type",
                "theme": "custom",
                "labelProp": "displayName",
                "valueProp": "id",
                "inline": true,
                "required": true,
                "options": [
                  { "displayName": "Internal", "id": "internal" },
                  { "displayName": "External", "id": "external" }
                ]
              }
            }
          ]
        },
        {
          "title": "Internal",
          "disabledExpression": "model.type !== \"internal\"",
          "fields": [
            {
              "key": "workforceId",
              "type": "input",
              "templateOptions": { "label": "workforceId", "required": true }
            }
          ]
        },
        {
          "title": "External",
          "disabledExpression": "model.type !== \"external\"",
          "fields": [
            {
              "key": "email",
              "type": "email",
              "templateOptions": { "label": "email", "required": true }
            }
          ]
        }
      ]
    }
  }
]

The following show how to activate the next step once a model value has changed:

[
  {
    "type": "wizard",
    "templateOptions": {
      "steps": [
        {
          "title": "Personal Information",
          "canExitExpression": "!!model.type",
          "fields": [
            {
              "type": "radio",
              "key": "type",
              "className": "col-sm-12",
              "templateOptions": {
                "label": "User Type",
                "theme": "custom",
                "labelProp": "displayName",
                "valueProp": "id",
                "inline": true,
                "required": true,
                "options": [
                  { "displayName": "Internal", "id": "internal" },
                  { "displayName": "External", "id": "external" }
                ]
              }
            }
          ]
        },
        {
          "title": "Internal",
          "disabledExpression": "model.type !== \"internal\"",
          "fields": [
            {
              "key": "workforceId",
              "type": "input",
              "className": "col-sm-12",
              "templateOptions": { "label": "workforceId", "required": true }
            }
          ]
        },
        {
          "title": "External",
          "disabledExpression": "model.type !== \"external\"",
          "fields": [
            {
              "key": "email",
              "type": "email",
              "className": "col-sm-12",
              "templateOptions": { "label": "email", "required": true }
            }
          ]
        }
      ]
    }
  }
]

additional controls

documentation comming soon

email

number

nested

static

date

k5-prefixed-input

k5-multi-checkbox

k5-merge-ui

← Karma Forms
  • k5-repeat-section
  • k5-collapse
  • k5-select
  • html
  • button
  • intro
    • Example
    • Template Options
  • unique-input
  • k5-paged-list
  • json-tree
  • dal-input
  • k5-tabset
  • wizard
  • additional controls
    • email
    • number
    • nested
    • static
    • date
    • k5-prefixed-input
    • k5-multi-checkbox
    • k5-merge-ui
Karma
Docs
Getting StartedConfiguration GuideForm Reference
Contact
Contact Kenoxa
More
ChangelogKenoxa
Copyright © 2025 Kenoxa GmbH