# ui-builder

## Install

```bash
npm i @appscode/ui-builder
```

## Usage

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

```js
// 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

```js
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 -

```html
<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 -
  ```js
  [
    {
      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](https://github.com/appscode/ui-builder/blob/master/MODULARITY_README.md)

## 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](https://github.com/appscode/ui-builder/blob/master/MODULARITY_README.md)

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

```json
{
  "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

```json
{
    "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](https://vuejs.org/v2/guide/class-and-style.html#Object-Syntax-1) 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:

```json
{
  "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 -

```json
{
  "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 -

```json
{
  "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 -

```json
{
  "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 -

```json
{
  "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 -

```json
{
  "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 -

```json
{
  "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](https://www.w3schools.com/jsref/prop_anchor_target.asp)

  - `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 the`path` 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 the`model`object, the`discriminator`of the wrapping single input form or the`Vuex Store` object.

    - `path` - It is a string denoting a [javascript template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) . 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 -

```json
{
  "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](https://www.w3schools.com/jsref/prop_anchor_target.asp)

  - `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 the`path` 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 the`model`object, the`discriminator`of the wrapping single input form or the`Vuex Store` object.

    - `path` - It is a string denoting a [javascript template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) . 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 -

```json
{
  "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 `model`object, the`router` 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 `model`object, the`router` 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 -

```json
{
  "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 -

```json
{
  "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 -

```json
{
  "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` -

```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](https://www.w3schools.com/jsref/prop_anchor_target.asp)

- `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 the`path` 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 the`model`object, the`discriminator`of the wrapping single input form or the`Vuex Store` object.

  - `path` - It is a string denoting a [javascript template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) . 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` -

```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` -

```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` -

```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 -

```json
{
  "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 -

```json
{
  "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:

```json
{
  "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 the`path` 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 the`model`object, the`discriminator`of the wrapping single input form or the`Vuex Store` object.

- `path` - It is a string denoting a [javascript template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) . 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](https://www.npmjs.com/package/@appscode/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](https://www.npmjs.com/package/@appscode/json-filter).

  **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:
    ```json
    "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:

```json
{
  "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:

```json
{
  "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:

```json
{
  "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.

```json
{
  "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:

```json
{
  "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.

```json
{
  "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.

```json
{
  "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 -

  ```json
  // 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.

  ```js
  // 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 argument of the function. User has access to the following elements from the `context` object -

### Object properties

- `model` - Contains a cloned copy of the `model.json` object.
- `elementSchema` - Contains a cloned copy of the element's `schema` from which the function is referenced.
- `rootSchema` - Contains a cloned copy of the whole `schema` of the ui-builder.
- `elementUi` - Contains a cloned copy of the element's `ui` object from which the function is referenced.
- `rootUi` - Contains a cloned copy of the whole `ui` object of the ui-builder.
- `discriminator` Contains a cloned copy of the `discriminator` object from the `single-step-form` element. it
- `rootModel` Contains a cloned copy of the whole `model` of the `single-step-form` element,

### For API calls

- `axios` - References the `axios` object which the ui-builder uses to make api calls. The user can use this `axios` instance to make api calls from the function.
- `qs` - References the query string parsing and stringifying library [`qs`](https://www.npmjs.com/package/qs). Users can use it to convert the request object to query string before making an api call.

### Method properties

- `getValue` - References the `getValue` method. It can be used to fetch values from an object by providing the object and a valid path. eg `const applyingForPosition = getValue(model, "/applyingForPosition")`
- `commit` - References the `this.$store.commit` method. It can be used to `commit` `vuex` store variables.
- ``watchDependency`- This method is used to pass dependency variables and their paths to an`dependency`object. The ui-bulder will keep track of these variables and recall the function whenever they change. eg -`watchDependency("model#/cloud/topStory");`
- `loadLocalFile` - This method is used to load data from local files from `"src/assets/wizard-resources"` directory. eg - `const localFile = await loadLocalFile("demo.json");`. If the file doesn't exist it will return an error. You can wrap the function in try catch block to catch and handle the error.
- `loadLocalJsModule` - This method is used to load JS file from local files from `"src/assets/wizard-resources"` directory. eg - `const localJsFile = await loadLocalJsModule("demo.js");`. If the file doesn't exist it will return an error. You can wrap the function in try catch block to catch and handle the error.
- `storeGet` - References a `vuex` getter function that can be used to get the value of any store variable, given a valid path. Eg - `const userId = storeGet("/user/data/uid")`.
- `updateModelValue` - to update the modelValue of `rootModel`. It is needed for adding/updating modelValue of `single-step-form-array` element.
- `setDiscriminatorValue` - This method is used to set value of a scoped `discriminator`. eg - `setDiscriminatorValue(path, value)`. where `path` refers to the discriminator's path and value refers to it's value.

### Route object

- `route` - Contains the vue route object.

### Examples

Some examples of functions in `function.js` are given below -

```js
function isActiveTab({ discriminator, getValue }, value) {
  const applyingForPosition = getValue(discriminator, "/activeTab");
  return applyingForPosition === value;
}
```

```js
async function fetchStoryComments({ axios, getValue, model, watchDependency }) {
  const storyId = getValue(model, "/cloud/topStory");
  // add storyId to watchDependencies to react to changes in it's value
  watchDependency("model#/cloud/topStory");

  if (storyId) {
    const resp = await axios.get(`/item/${storyId}.json`);
    return (
      resp.data?.kids?.map((comment) => ({
        text: comment,
        value: comment,
      })) || []
    );
  } else return [];
}
```

```js
async function createPost({ storeGet, watchDependency, axios, qs }) {
  const postOb = {
    body: "This is a demo post by s4k1b",
    title: "demo post sakib",
    userId: storeGet("/user/data/uid"),
  };
  // watch user id
  watchDependency("store#/user/data/uid");

  const url = "https://jsonplaceholder.typicode.com/posts";

  const resp = axios.post(url, qs.stringify(postOb), {
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
  });

  return resp.data?.id;
}
```

---

## `language`

The `language.json` file will contain user defined messages for the `vue-i18n` plugin to use for localization of the wizard. All the components of UI BUILDER fully supports localization.

_NOTE: For this to work, vue-i18n plugin has to be installed for your project._

Example language.json :

```json
{
  "en": {
    "info_true": {
      "label": "All information provided will be true"
    },
    "description": {
      "label": "Description"
    }
  },
  "bn": {
    "info_true": {
      "label": "প্রদত্ত সমস্ত তথ্য সত্য হবে"
    },
    "description": {
      "label": "বর্ণনা"
    }
  }
}
```

In the above example we see that we have localization available for `en` and `bn` languages. Offcourse these language keywords `en/bn` have to match the `vue-i18n`'s language keywords in your project.

Now in your `ui.json` you can provide a valid path from the message object and `vue-i18n` will show the translated message depending on your active local.

Example ui.json:

```json
{
  "label": {
    "text": "info_true.label"
  },
  "type": "switch",
  "schema": {
    "$ref": "schema#/properties/infoTrue"
  }
}
```

- When active local is `en` the label of the switch element will be "All information provided will be true"
- When active local is `bn` the label of the switch element will be "প্রদত্ত সমস্ত তথ্য সত্য হবে".

### Keywords

There are some paths in the `language.json` that are preserved as keywords by the UI BUILDER. These paths are used to show the default ui elements in our UI Builder components such as:

- Button labels for the bottom action bar
- Steps label for the sidebar
- Button labels for array/list/object/keyvalue/single-step-form-array input components.

You can override these paths in `language.json` and the ui-builder will use your given translations for those ui elements. Otherwise it will use default english values.

Keyword paths are -

```json
{
  "en": {
    "steps": {
      // multistep sidebar title
      "title": "STEPS"
    },
    "buttons": {
      // bottom control buttons
      "cancle": "Cancel",
      "previous": "Previous",
      "next": "Next",
      "preview": "Preview",
      "done": "Done",
      "deploy": "Deploy",
      // array-input-form / object-input-form / list-input-form / keyvalue-input-form / single-step-form-array buttons
      "add_new": "Add New",
      "edit": "Edit",
      "delete": "Delete",
      "show_details": "Show Details",
      "hide_details": "Hide Details",
      "close": "Close",
      "update": "Update",
      "info": "Description"
    },
    "editor": {
      "tabs": {
        // code editor tabs
        "code": "Code",
        "preview": "Preview Changes"
      }
    }
  }
  "bn": {
    // provide Bangla alternatives for each of the keywords here
  }
}
```

---

## Project setup

```

npm install

```

### Compiles and hot-reloads for development

```

npm run serve

```

### Compiles and minifies for production

```

npm run build

```

### Lints and fixes files

```

npm run lint

```

### Customize configuration

See [Configuration Reference](https://cli.vuejs.org/config/).

```

```
