@appscode/ui-builder

## Motivation

Usage no npm install needed!

<script type="module">
  import appscodeUiBuilder from 'https://cdn.skypack.dev/@appscode/ui-builder';
</script>

README

ui-builder

Install

npm i @appscode/ui-builder

Usage

For Nuxt, create a ui-builder.js file inside your plugins folder.

// plugins/ui-builder.js
import Vue from "vue";
import UiBuilder from "@appscode/ui-builder";

export default ({ store }) => {
  // reason for using preserveState false https://vuex.vuejs.org/guide/modules.html#preserving-state
  Vue.use(UiBuilder, { store, storeOptions: { preserveState: false } });
};

Vue.use will register the component globally, so you can call this component from anythere in your Nuxt/Vue app. Notice, we also passed our store object into the Vue.use function. This will register a wizard store module to your vuex store. You need to populate this module's state (ui, schema, model and functions objects) before you call this component. You can do this by calling the wizard module's mutations

this.$store.commit("wizard/ui$set", uiJson);
this.$store.commit("wizard/schema$set", schemaJson);

this.$store.commit("wizard/model$init", modelJson);

this.$store.commit("wizard/functions$set", modelJson);

// initialize configureOptions array with the id of the steps that you wnat to be skipped
this.$store.commit("wizard/configureOptions$set", ["basic"]);

We will discuss more about these ui, schema, model and functions objects below.

Finally now, we can call our <ui-builder> component -

<ui-builder
  :show-options-step="showOptionsStep"
  :on-options-valid="onOptionsValid"
  :on-options-invalid="onOptionsInvalid"
  :on-options-cancel="onOptionsCancel"
  :on-valid="onValid"
  :on-invalid="onInvalid"
  :on-cancel="onCancel"
  :on-deploy="onDeploy"
  :chart-url="https://demo_url"
/>
  • showOptionsStep - It denotes whether or not the wizard contains an options step. If true, two types of jsons should be provided, 1 for options and 1 for actual wizard, along with the onOptions functions. If false or not provided, the onOptions functions and options jsons are not required.
  • onOptionsValid - This function will be executed when user clicks the done button from the options step and the options wizard is in valid state.
  • onOptionsInvalid - It's executed in the final step, when the user clicks the done button from the options step and the options wizard is in invalid state.
  • onOptionsCancel - It will be executed when the user clicks the cancel button from the options step.
  • onValid - This function will be executed whenever preview step is shown (user clicks the final step done button) and the wizard is in valid state. The return value of this function will provide the preview step with the files to show. The return value of the function should be in the following format -
    [
      {
        name: "file1", /*name of the file*/
        content: "conent for file 1" /*content of the file*/
      },
      {
        name: "file2", /*name of the file*/
        content: "conent for file 2" /*content of the file*/
      },
      ...
    ]
    
  • onInvalid - It's executed in the final step, when the user clicks the done button and the wizard is in invalid state.
  • onCancel - It will be executed when the user clicks the cancel button from the wizard.
  • onDeploy - It will be execute when the user clicks on the deploy button from the preview step.
  • chartUrl - It denotes the default url for fetching reusable elements.

Motivation

Currently our charts include an openapi v3 schema. We are able to generate a HTML form from such a schema https://byte-builders-form.web.app/ .

But the ux of such an auto generated form is quite lacking compared to an hand written form. ui.json is a complementary json file format to any openapi_v3_schema.json to for schema driven form generation with no compromise on ux. Moreover, it can be used to generate UIs other than forms such as api driven list pages and details pages.

Observation

ui.json will need to include 3 types of information in addition to the schema.

  • Layout
  • Data Loaders
  • Conditional UI Elements
  • Validations

ui.json will be agnostic to any JS framework like Vue.js, React, etc.. Our implementation will be done for Vue.js.

Key objects

  • ui -> The json describing the ui layout and html structure
  • schema -> The json describing the structure of the form. Follows OpenAPIV3 standards. Must not be emtpy
  • baseModel -> The initial values, can be empty.
  • model -> Output of the form after user interaction.
  • keepEmptyModel -> Flag Objects for model attributes. If corresponding model value of any ui elements is allowed to be empty, Then value of that path will be true in this object.
  • asyncData -> cache of data loaded vai http call (This is an optimization and can be skipped).
  • functions -> An object containing functions that can be referenced from ui.json to perform complex operations.
  • language - An object containg vue-i18n supported messages for localization of the wizard

These objects will be used to interpolate output, pre-fill fields and generate conditional UI elements and load data.

Modularity

UI Builder is fully moduler. You can divide the ui.json along with it's associated language.json and function.js into several smaller modules and reference them inside your main ui.json.

Read more about modularity from here

Object Description

ui

This descibes the ui and it's constituent elements. The whole UI of the application is redered by interpolating over this object. It should describe each and every UI element that should be present in the form or wizard.

Coniditional elements should also be described here as well as the conditions based on which they will be rendered.

Data fetching from API calls should also be described here. It should contain all relavent information associalted with making the API call.

There can be several different structures of this ui schema, each responsible for generating different uis. One common property of this schema is the type property. It indicates which type of ui this schema is ment to generate. The rest of the properties depend on this type property.

The type property

The type property determines the type of ui component the ui.json schema is describing. The types are -

  • multi-step-form - also known as wizard.
  • single-step-form - also knows as simple form.
  • array-input-form - used for taking input array type elements.
  • opject-input-form - used for taking input object type (key value pairs) elements.
  • input - simple input box
  • textarea - simple textarea
  • editor - editor similar to vscode
  • select - simple select box
  • checkbox - checkboxes
  • radio - radio elements
  • switch - switch/toggle elements
  • tabs - simple tabs
  • anchor - used for showing anchor type buttons for going to external or internal links
  • reusable-element - used for reusing modules. Read more about modularity from here

The rest of the properties in ui.json differs depending on the type property.

The keepEmpty property

The keepEmpty property indicates the ui component's corresponding model value can be a empty value or not. Type of this attribute is boolean -

  • true - The model value of this path can be empty. In corresposing path of schema for that component, will be set to true in keepEmptyModel.
  • false - The model value of this path can not be empty. Using this final model value's empty object can be trimmed.

The Multi Step Form

Example of ui.json for mulit step form

{
  "type": "multi-step-form",
  "steps": [
    {
      "if": {
        ...
        ...
      },
      "title": "General Information",
      "form": {
        "type": "single-step-form",
        .....
        .....
      }
    },
    {
      "if": {
        ...
        ...
      },
      "title": "Topology",
      "form": {
        "type": "single-step-form",
        .....
        .....
      }
    },
    ........
    ........
  ]
}

From the example we see that the multi-step-form has 2 more porperties in addition to the type property. They are -

  • steps - It is an array type property describing all the steps of the multi step form. Each step of a multistep form contains a single step form. It contains two properties -

    • if[OPTIONAL] - contains the description of the condition upon which the rendering of the form depends on. If the condition returns true, the form is rendered otherwise it is hidded from view. For more details [click here](#The if property)
    • title - The of the step.
    • form - A ui.json of type single-step-form / multi-step-form.

    Every step of a multi-step-form must be a single-step-form or a multi-step-form. The multi-step-form inside the steps array will be automatically nested in the UI.

The Single Step Form

Example of ui.json for single step form

{
    "type": "single-step-form",
    "label": "demo form",
    "show_label": true,
    "discriminator": {
        ....
        ....
    },
    "if": {
        ....
        ....
    },
    "elements": [
        {
            "type": "select",
            ....
            ....
        },
        ....
        ....
    ],
    "style": {
      "paddingLeft": "20px"
    }
}

The properties are described below -

  • label[OPTIONAL] - denotes the label for the form. It is optional, if not provided no labels will be shown for the form.

  • show_label[OPTIONAL] - specifies if we want to show the label of the form in the ui or not. It defaults to false, that means by default label is not shown. But when specied as true the label will be shown in the ui.

  • discriminator[OPTIONAL] - contains the schema of the variables which are not in model object or inside our store object in vue. These variables are needed when the rendering of the form elements depends on values that are neither in model object nor in store object.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the form depends on. If the condition returns true, the form is rendered otherwise it is hidded from view. For more details [click here](#The if property)

  • elements - It is an array containing the list of all the elements within the form. Each item contains the ui.json of a simple form element. They can be -

    • input type

    • textarea type

    • editor type

    • select type

    • anchor type

    • checkbox type

    • radio type

    • switch type

    • array-input-form type

    • object-input-form type

    • single-step-form type

    • tabs type

    note: Multi step form can not be an element of Single step form.

  • style[OPTIONAL] - contains a style object that can be used to bind inline styles to the single step form element.

The List Input Form

List input form is a form element that is used to take list of string as input from users. The example of ui.json for list input form:

{
  "type": "list-input-form",
  "label": {
   "text": "Demo list input form"
  },
  "if": {
    ...
    ...
  },
  "fetch": {
    ....
    ....
  },
  "element": {
    "type": "input",
    ...
    ...
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true,
  "individualItemDisabilityCheck": "demoChecker"
}

The properties are described below -

  • label - The label property describes the label element for the list input form.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the list input form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fill the input field with data.

  • element - contains the ui.json for a single list element. A single list element can be -

    • input type
  • schema - contains the JSON Schema or the reference to the schema for the array type variable that is being modified by the array input form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the list input form is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • individualItemDisabilityCheck[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual list items as itemCtx inside the context object and returns a Boolean value. If true the individual list items will not be modifiable otherwise items will be be modifiable. DEFAULTS TO false. itemCtx for this will contain the string value of a particular item in list input form.

The Key Value Input Form

key value input form is a form element that is used to take the key value elements of an object from users. The example ui.json is given below -

{
  "type": "key-value-input-form",
  "label": {
    "text": "Demo key value input form"
  },
  "isArray": true,
  "if": {
    ...
    ...
  },
  "fetch": {
    ....
    ....
  },
  "keys": {
    "label": {
      "text": "Demo key"
    }
  },
  "values": {
    "type": "input",
    ...
    ...
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true,
  "individualItemDisabilityCheck": "demoChecker",
  "newItemValidator": "demoValidator",
}
  • label - The label property describes the label element for the key value input form.

  • isArray[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the key value input field can be multiple.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the key value input form element depends on. If the condition returns true, the form element is rendered otherwise it is hidden from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fill the key, value input fields of the key value input form with data.

  • keys - contains the label of the input field for the keys of the object. This label property is an object that is similar to label of key value input form.

  • values - contains the ui.json for a key value. A single value can be -

    • input type
  • schema - contains the JSON Schema or the reference to the schema for the object type variable that is being modified by the key value input form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the key value input form is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • individualItemDisabilityCheck[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual key value items as itemCtx inside the context object and returns a Boolean value. If true the individual key value items will not be modifiable otherwise key value items will be be modifiable. DEFAULTS TO false. itemCtx for this will contain an object like -

    {
      key: "demo_key",
      value: "Demo Value"
    }
    

    for a particular item in key value input form.

  • newItemValidator[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual key value items as itemCtx inside the context object which is candidate item for adding and returns an object. If the individual key value items is valid it returning empty object is okay. Otherwise it returns a object like -

    {
      isInvalid: true,
      message: "demo message to show"
    }
    

    itemCtx for this will contain an object like -

    {
      key: "demo_key",
      value: "Demo Value"
    }
    

    for a particular item in key value input form.

The Key TextArea Input Form

key text area input form is a form element that is used to take the key value elements of an object from users where value input field will be an textarea field. The example ui.json is given below -

{
  "type": "key-text-area-input-form",
  "label": {
    "text": "Demo key area input form"
  },
  "isArray": true,
  "if": {
    ...
    ...
  },
  "fetch": {
    ....
    ....
  },
  "keys": {
    "label": {
      "text": "Demo key"
    }
  },
  "values": {
    "type": "input",
    ...
    ...
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true,
  "individualItemDisabilityCheck": "demoChecker",
  "newItemValidator": "demoValidator",
}
  • label - The label property describes the label element for the key text area input form.

  • isArray[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the key value input field can be multiple.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the key value input form element depends on. If the condition returns true, the form element is rendered otherwise it is hidden from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fill the key, value input fields of the key value input form with data.

  • keys - contains the label of the input field for the keys of the object. This label property is an object that is similar to label of key text area input form.

  • values - contains the ui.json for a key value. A single value can be -

    • input type
  • schema - contains the JSON Schema or the reference to the schema for the object type variable that is being modified by the key text area input form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the key value input form is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • individualItemDisabilityCheck[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual key value items as itemCtx inside the context object and returns a Boolean value. If true the individual key value items will not be modifiable otherwise key value items will be be modifiable. DEFAULTS TO false. itemCtx for this will contain an object like -

    {
      key: "demo_key",
      value: "Demo Value"
    }
    

    for a particular item in key value input form.

The "Input" Form Element

The "Input" form element is a type of form element which is used to take a simple string, number or date as input. An example of ui.json for a input form element is given below -

{
  "type": "input",
  "label": {
    "text": "Demo input form element"
  },
  "if": {
    ....
    ....
  },
  "fetch": {
    ....
    ....
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true,
  "hideValue: true
}

The properties are described below -

  • label - The label property describes the label element for the simple input form.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the input form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fill the input field with data.

  • schema - contains the JSON Schema or the reference to the schema for the string / number / date type variable that is being modified by the input form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the input field is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • hideValue[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the value of input field will be password type.

The "Textarea" Form Element

The "Textarea" form element is similer to the "Input" form element. It is useful when the string inside the input field is multilined.An example of ui.json for a textarea form element is given below -

{
  "type": "textarea",
  "label": {
    "text": "Demo textarea form element"
  },
  "if": {
    ....
    ....
  },
  "fetch": {
    ....
    ....
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true
}

The properties are described below -

  • label - The label property describes the label element for the textarea input form.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the textarea form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fill the textarea with data.

  • schema - contains the JSON Schema or the reference to the schema for the string / number / date type variable that is being modified by the textarea form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the textarea field is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

The "Editor" Form Element

The "Editor" form element renders a code editor similar to VS Code. It is useful when the content needed to be edited is a code file.An example of ui.json for a editor form element is given below -

{
  "type": "editor",
  "label": {
    "text": "Demo editor form element"
  },
  "language": "json",
  "if": {
    ....
    ....
  },
  "fetch": {
    ....
    ....
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true
}

The properties are described below -

  • label - The label property describes the label element for the editor input form.

  • language - The programming language of the content. Currently only text, json and yaml languages are supported.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the editor form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fill the editor with data.

  • schema - contains the JSON Schema or the reference to the schema for the string type variable that is being modified by the editor form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the editor field is readonly and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

The "Select" Form Element

The "Select" form element is a type of form element which is used to select one option from a number of provided options. An example fo the ui.json is given below -

{
  "type": "select",
  "label": {
    "text": "Department"
  },
  "if": {
    ....
    ....
  },
  "fetch": {
    ....
    ....
  },
  "options": [
    {
      "value": "cse",
      "text": "Department of Computer Science & Engineering"
    },
    {
      "value": "ict",
      "text": "Department of Information & Communication Technology"
    }
  ],
  "add_new_button": {
    "label": "Add new item",
    "url": {
      "params": {
        "name": {
          "$ref": "model#/name"
        }
      },
      "path": "/${name}"
    },
    "target": "_blank"
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": false,
  "individualItemDisabilityCheck": "demoChecker",
  "allowUserDefinedOption": true,
}

The properties are described below -

  • label - The label property describes the label element for the select form element.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the select form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fetch the options for the select form. Only required if the options are not provided directly here

  • options - contains an array of object or string representing the selectable options. One of which is selected using the select element. If contains object, then each option element has 2 properties -

    • value - The value attribute for the option element. It is the value that will be saved in the model object if the user selects the option.

    • text - The actual text that will represent the option to the user in the UI.

    otherwise, each element will be array of strings refering value and text to display both.

  • add_new_button[OPTIONAL] - This property is used if you want to add a "Add New" button to the select options. This select option acts as a anchor element and clicking it will take the user to a specified url is the current tab or new tab. All of this is configurable. It has 3 properties :

    • label - The label of the option. This is text that is displayed inside the option button.

    • target - The target attribute specifies where to open the link. Read more from [here](HTML DOM Anchor target Property

    • url - This property describes the url that is the href of the anchor select element. It has the following properties -

      • params- describes the name and json reference of the variables that are used in thepath property as placeholders. All the variables that are used in the path property must be declared here first. The json reference for the varaibles can be from themodelobject, thediscriminatorof the wrapping single input form or theVuex Store object.

      • path - It is a string denoting a javascript template literal . The placeholders inside the literal must declared in the params property. The actual path is calculated by replacing the placeholders with their actual value. path property is evaluated to get our href for the anchor select element.

  • schema - contains the JSON Schema or the reference to the schema for the string / number type variable that is being modified by the select form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the select field is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • individualItemDisabilityCheck[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual key value items as itemCtx inside the context object and returns a Boolean value. If true the individual options in the select box will not be selectable otherwise options in the select form element will be be selectable. DEFAULTS TO false. itemCtx for this will contain an object like -

    {
      text: "demo text",
      value: "demo_value"
    }
    

    for a particular option in the Select form element.

  • allowUserDefinedOption[OPTIONAL] - If not specified, it is false by default. If specified and set to true, user can add new element to the option list.

The "Multiselect" Form Element

The "Multiselect" form element is a type of form element which is used to select one or multiple option from a number of provided options. An example fo the ui.json is given below -

{
  "type": "multiselect",
  "label": {
    "text": "Department"
  },
  "if": {
    ....
    ....
  },
  "fetch": {
    ....
    ....
  },
  "options": [
    {
      "value": "cse",
      "text": "Department of Computer Science & Engineering"
    },
    {
      "value": "ict",
      "text": "Department of Information & Communication Technology"
    }
  ],
  "add_new_button": {
    "label": "Add new item",
    "url": {
      "params": {
        "name": {
          "$ref": "model#/name"
        }
      },
      "path": "/${name}"
    },
    "target": "_blank"
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": false,
  "individualItemDisabilityCheck": "demoChecker",
  "allowUserDefinedOption": true,
}

The properties are described below -

  • label - The label property describes the label element for the multiselect form element.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the multiselect form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fetch the options for the multiselect form. Only required if the options are not provided directly here

  • options - contains an array of object or string representing the selectable options. If contains object, then each option element has 2 properties -

    • value - The value attribute for the option element. It is the value that will be saved in the model object if the user selects the option.

    • text - The actual text that will represent the option to the user in the UI.

    otherwise, each element will be array of strings refering value and text to display both.

  • add_new_button[OPTIONAL] - This property is used if you want to add a "Add New" button to the select options. This select option acts as a anchor element and clicking it will take the user to a specified url is the current tab or new tab. All of this is configurable. It has 3 properties :

    • label - The label of the option. This is text that is displayed inside the option button.

    • target - The target attribute specifies where to open the link. Read more from [here](HTML DOM Anchor target Property

    • url - This property describes the url that is the href of the anchor select element. It has the following properties -

      • params- describes the name and json reference of the variables that are used in thepath property as placeholders. All the variables that are used in the path property must be declared here first. The json reference for the varaibles can be from themodelobject, thediscriminatorof the wrapping single input form or theVuex Store object.

      • path - It is a string denoting a javascript template literal . The placeholders inside the literal must declared in the params property. The actual path is calculated by replacing the placeholders with their actual value. path property is evaluated to get our href for the anchor select element.

  • schema - contains the JSON Schema or the reference to the schema for the string / number type variable that is being modified by the select form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the select field is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • individualItemDisabilityCheck[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual key value items as itemCtx inside the context object and returns a Boolean value. If true the individual options in the select box will not be selectable otherwise options in the multiselect form element will be be selectable. DEFAULTS TO false. itemCtx for this will contain an object like -

    {
      text: "demo text",
      value: "demo_value"
    }
    

    for a particular option in the Multiselect form element.

  • allowUserDefinedOption[OPTIONAL] - If not specified, it is false by default. If specified and set to true, user can add new element to the option list.

The "Configure Options" Form Element

The "Configure Options" form element is a type of form element which is used to render special checkbox field where users can check their needed configuration items. An example of the ui.json is given below -

{
  "type": "configure-options",
  "label": {
    "text": "Demo configure options"
  },
  "hasDescription": true,
  "hasDependencies": true,
  "if": {
    ....
    ....
  },
  "fetch": {
    ....
    ....
  },
  "owner": {
    "$ref": "store#/user/username"
  },
  "cluster": {
    "$ref": "store#/clusterInfo/name"
  },
  "options": [
    {
      "value": "demo1",
      "text": "Demo 1",
      "description": "Description of demo 1",
      "dependencies": [{
        "name": "demo Dependency",
        "url": "demo_url"
      }],
      "disabled": true
    },
    {
      "value": "demo2",
      "text": "Demo 2",
      "description": "Description of demo 2"
    }
  ],
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true,
}

The properties are described below -

  • label - The label property describes the label element for the configure options input form.

  • owner - It can be string or object type value. If string the owner's value will be directly set. Otherwise, it describes the json reference of the variables that are used to set owner value.

    • $ref - contains the JSON reference string. The json reference for the varaibles can be from the modelobject, therouter object of the current route or the store as Vuex Store object.
  • cluster - It can be string or object type value. If string the cluster's value will be directly set. Otherwise, it describes the json reference of the variables that are used to set cluster value.

    • $ref - contains the JSON reference string. The json reference for the varaibles can be from the modelobject, therouter object of the current route or the store as Vuex Store object.
  • hasDescription[OPTIONAL] - It indicates whether or not the options of the checkbox items contain any kind of description. It is by default false. If set to true, the options of the checkbox must contain the description property.

  • hasDependency[OPTIONAL] - It indicates whether or not the options of the checkbox items may contain any kind of dependencies. It is by default false. If set to true, the options of the checkbox may contain the dependencies property.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the checkbox form element depends on. If the condition returns true, the form element is rendered otherwise it is hidden from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fetch the options for the checkbox form element. Only required if the options are not provided directly here

  • options - contains an array of object representing the selectable options. Each option element has 2 properties -

    • value - The value attribute for the option element. It is the value that will be saved in the model object if the user selects the option.

    • text - The actual text that will represent the option to the user in the UI.

    • description[OPTIONAL] - This contains some description about the option. It's optional, if the hasDescription property is set to true this descrption will be shown.

    • dependencies[OPTIONAL] - contains an array of dependencies objects each describing a dependency element. Each dependencies object has 2 properties -

      • name - Name of the dependency

      • url - URL link for the dependency

    • disabled[OPTIONAL] - This indicates the particular option is disabled or not. If not specified, it is false by default.

  • schema - contains the JSON Schema or the reference to the schema for the string / number type variable that is being modified by the configuration options form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the checkbox field is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • individualItemDisabilityCheck[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual configure option items as itemCtx inside the context object and returns a Boolean value. If true the individual list items will not be modifiable otherwise items will be be modifiable. DEFAULTS TO false. itemCtx for this will contain the object value of a particular item in Configure Options Form.

The "Checkbox" Form Element

The "Checkbox" form element is a type of form element which is used to render checkboxes. Users one can check one or more items. An example fo the ui.json is given below -

{
  "type": "checkbox",
  "label": {
    "text": "Demo checkbox"
  },
  "hasDescription": true,
  "if": {
    ....
    ....
  },
  "fetch": {
    ....
    ....
  },
  "options": [
    {
      "value": "demo1",
      "text": "Demo 1",
      "description": "Description of demo 1"
    },
    {
      "value": "demo2",
      "text": "Demo 2",
      "description": "Description of demo 2"
    }
  ],
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true,
  "individualItemDisabilityCheck": "demoChecker"
}

The properties are described below -

  • label - The label property describes the label element for the checkbox form element.

  • hasDescription[OPTIONAL] - It indicates whether or not the options of the checkbox items contain any kind of description. It is by default false. If set to true, the options of the checkbox must contain the description property.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the checkbox form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fetch the options for the checkbox form element. Only required if the options are not provided directly here

  • options - contains an array of object representing the selectable options. Each option element has 2 properties -

    • value - The value attribute for the option element. It is the value that will be saved in the model object if the user selects the option.

    • text - The actual text that will represent the option to the user in the UI.

    • description[OPTIONAL] - This contains some description about the option. It's optional, if the hasDescription property is set to true this descrption will be shown.

  • schema - contains the JSON Schema or the reference to the schema for the string / number type variable that is being modified by the checkbox form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the checkbox field is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • individualItemDisabilityCheck[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual key value items as itemCtx inside the context object and returns a Boolean value. If true the individual options in the checkbox will not be clickable otherwise options in the checkbox will be be clickable. DEFAULTS TO false. itemCtx for this will contain an object like -

    {
      text: "demo text",
      value: "demo_value"
    }
    

    for a particular option in the Checkbox.

The "Radio" Form Element

The "Radio" form element is a type of form element which is used to render radio elements. Users can pick only one item. An example fo the ui.json is given below -

{
  "type": "radio",
  "label": {
    "text": "Demo radio"
  },
  "if": {
    ....
    ....
  },
  "fetch": {
    ....
    ....
  },
  "options": [
    {
      "value": "demo1",
      "text": "Demo 1"
    },
    {
      "value": "demo2",
      "text": "Demo 2"
    }
  ],
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true,
  "individualItemDisabilityCheck": "demoChecker"
}

The properties are described below -

  • label - The label property describes the label element for the radio input form element.

  • hasDescription[OPTIONAL] - It indicates whether or not the options of the radio items contain any kind of description. It is by default false. If set to true, the options of the radio must contain the description property.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the radio form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fetch the options for the radio form element. Only required if the options are not provided directly here

  • options - contains an array of object representing the selectable options. Each option element has 2 properties -

    • value - The value attribute for the option element. It is the value that will be saved in the model object if the user selects the option.

    • text - The actual text that will represent the option to the user in the UI.

    • description[OPTIONAL] - This contains some description about the option. It's optional, if the hasDescription property is set to true this descrption will be shown.

  • schema - contains the JSON Schema or the reference to the schema for the string / number type variable that is being modified by the radio form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the radio field is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • individualItemDisabilityCheck[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual key value items as itemCtx inside the context object and returns a Boolean value. If true the individual options in the radio will not be clickable otherwise options in the radio will be be clickable. DEFAULTS TO false. itemCtx for this will contain an object like -

    {
      text: "demo text",
      value: "demo_value"
    }
    

    for a particular option in the Radio.

The "Switch" Form Element

The "Switch" form element is a type of form element which is used to take a simple boolean (true/false) as input. An example of ui.json for a switch form element is given below -

{
  "type": "switch",
  "label": {
    "text": "Demo switch"
  },
  "if": {
    ....
    ....
  },
  "fetch": {
    ....
    ....
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "disabled": true
}

The properties are described below -

  • label - The label property describes the label element for the switch form element.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the switch form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to set or reset the switch.

  • schema - contains the JSON Schema or the reference to the schema for the boolean variable that is being modified by the switch form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the switch field is disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

The "Anchor" Form Element

The "Anchor" form element is a type of form element which is used provide a link to the user. Users can click on the element to visit the link in the same tab or new tab. The link can point to same domain or different domain. An exampe ui.json -

{
   "type":"anchor",
   "label": {
     "text": "Demo anchor"
   },
   "target":"_blank",
   "url":{
      "params":{
         "name":{
            "$ref":"model#/name"
         }
      },
      "path":"/${name}"
   },
   "if":{
      ....
      ....
   },
   "disabled": true
}

The properties are described below -

  • label - The label property describes the label element for the anchor form element.

  • target - The target attribute specifies where to open the linked document. Read more from [here](HTML DOM Anchor target Property

  • url - This property describes the url that is the href of the anchor element. It has the following properties -

    • params- describes the name and json reference of the variables that are used in thepath property as placeholders. All the variables that are used in the path property must be declared here first. The json reference for the varaibles can be from themodelobject, thediscriminatorof the wrapping single input form or theVuex Store object.

    • path - It is a string denoting a javascript template literal . The placeholders inside the literal must declared in the params property. The actual path is calculated by replacing the placeholders with their actual value. path property is evaluated to get our href for the anchor element.

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the anchor element depends on. If the condition returns true, the element is rendered otherwise it is hidded from view.

  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the anchor button is disabled and can not be clicked. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

The "Label" Form Element

The "Label" form element is a type of form element that is used to show a field independent Label in form. An exampe ui.json -

{
  "type": "label-element",
  "label": {
    "text": "Demo Label",
    "hasLine": true,
    "isSubsection": true
  },
  "customClass": "mr-10"
}

The properties are described below -

  • label - The label property describes the label element for the label form element.

  • customClass[OPTIONAL] - Value type string. Pass custom class name for styling.

The "Tabs" Form Element

The "Tabs" form element is a type of form element that is used to switch between different forms that are in different tabs. Example of ui.json -

{
  "type": "tabs",
  "label": "Demo Tabs",
  "tabs": [
    {
      "value": "demo-value-1",
      "text": "Demo Value 1"
    },
    {
      "value": "demo-value-2",
      "text": "Demo Value 2"
    }
  ],
  "schema": {
    "$ref": "discriminator#/activeTab"
  }
}

The properties are described below -

  • label - The label of the tabs element. It is not shown in the UI, only needed for logical reasons.

  • tabs - contains an array of tab objects each describing a tab element. Each tab object has 2 properties -

    • value - The actual value that will be saved to a variable when the tab is selected by user

    • text The title of the tab that will be shown to the user.

  • schema - contains the JSON Schema or the reference to the schema for the string / number type variable that is being modified by the tabs form element.

    • $ref - contains the JSON reference string pointing to the JSON schema.

The Single Step Form Array

The single step form array is form that is used to take input array of object. An exampe ui.json -

{
  "type": "single-step-form-array",
  "label": {
    "text": "Demo Single Step Form Array"
  },
  "schema": {
    "$ref": "schema#/properties/..."
  },
  "addFormLabel": "demo form label",
  "tableContents": [
    {
      "type": "value",
      "typeOfValue": "string",
      "inTableColumn": true,
      "label": {
        "text": "Demo Label"
      },
      "path": "root/child1/child2/....",
      "tableContents": [
        ...
        ...
      ]
    }
  ],
  "element": {
    "type": "single-input-form",
    ...
    ...
  }
}

The properties are described below -

  • label - The label property describes the label element for the single step form array element.

  • addFormLabel this form label is used showing the new item adding button text,

  • if[OPTIONAL] - contains the description of the condition upon which the rendering of the array input form element depends on. If the condition returns true, the form element is rendered otherwise it is hidded from view.

  • fetch[OPTIONAL] - contains the description of the API that is needed to be called to fill the input field with data.

  • tableContents - contains information about attributes for each object to show the table view of objects. each item of this array contains -

    • type Possible value can be value or label

    • typeOfValue - Required, if type is set to value. Possible value can be string, array, key-value, code or key-operator-values-array,

    • inTableColummn - It indicates the visibility of this field in table column. If not specified, it is false by default.

    • label - Label object must contain text property. Also, It has 2 optional properties for styling -

      • text text part of the label. This part will be shown as table column name and label in details section.

      • hasLine [OPTIONAL] Value type boolean. Show an optional line for the label.

      • isSubsection [OPTIONAL] Value type boolean. Decrease font size for subsection label.

    • path to access the value from object item.

    • computed - to compute the value using function from function.js. After fetching the value it will be stored on declared path.

    • tableContents - contains information about attributes of child single-object-from-array for each object to show the table view of objects. It is required when child object is also a single-step-form-array.

  • element - contains the ui.json for a single array element. The ui for the existing array elements along with taking new array element as input is rendered using this ui.json. A single array element can be -

    • label-element type

    • input type

    • textarea type

    • editor type

    • select type

    • checkbox type

    • radio type

    • switch type

    • single-step-form type

    • array-input-form type

    • object-input-form type

  • schema - contains the JSON Schema or the reference to the schema for the array type variable that is being modified by the single step form array element.

    • $ref - contains the JSON reference string pointing to the JSON schema.
  • disabled[OPTIONAL] - If not specified, it is false by default. If specified and set to true, the single step form array will be disabled and can not be modified. If specified and set to a string value then it specifies the function name declared in function.js to set this value using functions.js.

  • newItemValidator[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual single step form array items as itemCtx inside the context object which is candidate item for adding and returns an object. If the individual single step form array item is valid, then returning empty object is okay. Otherwise it returns a object like -

    {
      isInvalid: true,
      message: "demo message to show"
    }
    

    for a particular item in key value input form.

  • individualItemDisabilityCheck[OPTIONAL] - Specifies the function name declared in function.js. This function takes individual list items as itemCtx inside the context object and should return an Object like -

  {
    isEditDisabled: true,
    isDeleteDisabeld: true,
  }

isEditDisabled indicates the the item will e editable or not. Similarly, isDeleteDisabled indicates the the item can be deleted or not.

The "Reusable-Element"

The reusable element is an element that is used to import and reuse wizard modules that are stored remotely and can be used in multiple places.

Special Properties

There are some special propertie such as discriminator, if, fetch that are used to equip the UI with special abilities such as conditional rendering of elements, fetching data using api calls, etc. Here, we will look a more detailed description about these properties.

The discriminator property

The discriminator is a property that is used inside a single-step-form to describe the schema of the variables which are not in model object or inside our store object in vue. These variables are needed when the rendering of the form elements depends on values that are neither in model object nor in store object.

In implementation, these variables are declared inside the SingleStepForm component and passed as a prop to the child form elements. The child form elements may reference these variables from inside their if or fetch property as parameters. Also, this value can be emitted to parent discriminator value, using emitAs property in discriminator.

An example of discriminator property is given below -

{
  "discriminator": {
    "activeTab": {
      "type": "string",
      "default": "default-tab",
      "emitAs": "demo_parent_discriminator_name_to_emit"
    }
  }
}

The schema described inside the discriminator follows the general Open API V3 schema conventions.

The if property

The if is a property that is used inside a form element such as single-step-form, array-input-form, object-input-fomr, input, select, checkbox, textarea, editor, radio, switch, anchor to describe the condition upon which the rendering of the form elements depends on. It is an optional property.

This property is optional for form elements, if mentioned then the condition is resolved and if the condition resolves to true, the form element is rendered otherwise it is hidden

An example is given below -

{
  "if": {
    "params": {
      "applyinForPosition": {
        "$ref": "model#/applyingForPosition"
      }
    },
    "expression": "applyingForPosition === 'fe-software-eng'"
  }
}
  • params - describes the name and json reference of the variables that are used in the expression for the evaluation of the conditoin. All the variables that are used in the expression must be declared here first. The json reference for the varaibles can be from the model object, the discriminator of the wrapping single input form or the Vuex Store object.

  • expression - it is a string describing the expression that is evaluated to resolve the condition. It is a simple javascript expression that is resolved using .eval() method. The variables used in this expression must be described in params first.

The fetch property

The fetch property is an optional property that is mentioned inside a form elemnt such as select, checkbox, radio where we require option list to be fetched via HTTP requests from external servers or load data from a file in project directory. This property describes the necessary elements requred to make the HTTP call from the UI.

Example:

{
  "fetch": {
    "type": "post",
    "data": {
      "type": "application/x-www-form-urlencoded",
      "params": {
        "userId": {
          "$ref": "store#/user/data/uid"
        },
        "body": "This is a demo post by s4k1b",
        "title": "demo post sakib"
      }
    },
    "params": {
      "storyId": {
        "$ref": "model#/cloud/topStory"
      }
    },
    "path": "/item/${storyId}.json",
    "filters": [
      {
        "$ref": "#/kids"
      },
      {
        "text": {
          "$ref": "#/"
        },
        "value": {
          "$ref": "#/"
        }
      }
    ]
  }
}
  • type - describes the type of the http call. It can be either "get" or "post".

  • data - Required only if the type is set as "post". It describes the post reqest body object. It has several properties -

    • type - describes the format of data to be sent. Can be either application/json or application/x-www-form-urlencoded. If set to application/json, the data object is sent as a plain JSON object. If set to application/x-www-form-urlencoded, the data object is formatted to a key value pair where the keys and values are encoded in key-value tuples separated by '&', with a '=' between the key and the value.

    • params - describes the actual body of the data object to be sent. It contains the data object property names and their values. It either contains the direct values or reference to the actual values.

  • params- describes the name and json reference of the variables that are used in thepath property as placeholders. All the variables that are used in the path property must be declared here first. The json reference for the varaibles can be from themodelobject, thediscriminatorof the wrapping single input form or theVuex Store object.

  • path - It is a string denoting a javascript template literal . The placeholders inside the literal must declared in the params property. The actual path is calculated by replacing the placeholders with their actual value. path property describes the url to which api requests are made.

  • filters - This property describes the array of operations required for json-filter to extract relevant value from our api response. If filters property is not provided, then the whole api response data is taken as our reponse value.

    • The user should filter the api response according to the form element. If the form element is input type, then filtered response should be string, If if element is array-input-form then filtered response should be array, if element is object-input-type then it should be object type and so on.

    • In case of select element, the filtered response should be an array of objects each containing two properties, text property and value property. The text property denotes the select option text and the value property denotes the value for that option.

    You can learn about how to write your filters according to your needs from here.

    You can also use fetch property to load data from a file stored in your asset folder:

    • The method prop in case of loading data from file is "load".
    • The file directory must be relative to your /src/assets/wizard-resources/ directory in your project folder.
    • There must be a /src/assets/wizard-resources/ directory in your project folder.
    • The url prop in case of loading data from file denotes the relative path for the file inside /src/assets/wizard-resources/ directory. All data files must be nested inside this directory.
    • Rest of the properties inside the fetch property acts in the same way as they did for making api calls.
    • Example:
      "fetch": {
        "method": "load",
        "filters": [
          {
            "value": {
              "$ref": "#/id"
            },
            "text": {
              "$ref": "#/file"
            }
          }
        ],
        "path": "demo.json"
      }
      

The computed property

The computed property is an optional property that is mentioned inside a form elemnt such as list-input-form, key-value-input-form,object-input-form,editor,input,textarea,array-input-form, select, checkbox, radio where we require the value of element to be set from function call using function.js .

Example:

{
  "computed": "demoFunction"
}

The customClass property

The customClass property is an optional property that is mentioned inside a form elemnt where we require to add any custom css class to that form element.

Example:

{
  "customClass": "mb-20"
}

The required property

The required property is an optional property that can be mentioned inside all form elemnt except reusable-element, multi-step-form where we require to set the element will be required field or not. The value can be two types. boolean or string. String value is used to set it using functions.js.

Example:

{
  "required": true
}

The onChange property

The onChange property is an optional property that can be used on any form element. It denotes a function name which must be declared in functions.js. This function is executed whenever the value of the correspoinding form element changes. User can perform their required task inside the function body.

{
  "onChange": "onChangeFunction"
}

The label property

This object is responsible to show label of a form element. Label object must contain text property. Also, It has 2 optional properties for styling -

Example:

{
  "label": {
    "text": "demo text",
    "hasLine": true,
    "isSubsection": true
  }
}
  • text The label text of the form element.

  • hasLine[OPTIONAL] Value type boolean. Show an optional line for the label. Default value is false.

  • isSubsection[OPTIONAL] Value type boolean. Decrease font size for subsection label. Default value is false.


The encoder property

Contains a string refers to the function from functions.js. This function is responsible for encode the value to appropiate format if needed.

{
  "encoder": "demoEncoderFunction"
}

The decoder property

Contains a string refers to the function from functions.js. This function is responsible for decode the value to appropiate format if needed.

{
  "decoder": "demoDecoderFunction"
}

functions

The functions.js file will contain user defined functions that can be referenced from ui.json and has access to a context variable that the user can use to perform complex tasks. Users can reference the functions from the fetch and if property in ui.json. Function name can not contain '|', ::' or '/' characters

Parameters

  • The first argument for each function is a context object, containig all necessary methods and data that the user needs access to in this function.

  • The remaining arguments ar passed by the user when the funtion is referenced from ui.json. eg -

    // example of passing arguments in function from ui.json
    {
      ...
      "if": "showAdditionalInfo|software-eng"
      ...
    }
    

    Here, showAdditionalInfo is a function declared in functions.js file. The 'software-eng' is a string that is passed as a second argument when the function is called.

    // example function.js declaring showAdditionalInfo function
    function showAdditionalInfo({ model, getValue }, value) {
      const applyingForPosition = getValue(model, "/applyingForPosition");
      return applyingForPosition === value;
    }
    

    In the above example the string 'software-eng' is passed as the parameter value. More paremeters can be passed by concatinating them using the | character in ui.json file. eg: funtionName|parameter1|parameter2|....

Return value

The return value of the function depends on which property it was referenced by in ui.json.

  • If the function was referenced in "if" property, the return value of the function should be a boolean value.
  • If the function was referenced in "fetch" property, the return value of the function should be in accordance with the required format by the ui element.

The context object

Each function in the function.js file has access to a context object that will be passed as first argum