UI Form
Objective
The Form is a UI library that generates a form look and feel to add/update the data and submit the changes. The library is available in Dashboard UI and can be invoked by any module.
Features
Feature | Description |
---|---|
Rendering | The form is provided with a fields array, each field is represented by a configuration object that states how it should be rendered. Based on these configuration objects, the form is populated. |
Operation Attaching | The form is passed on a list provided with the list buttons that will be displayed below the fields populate and the operations that should be triggered when these buttons are pressed. |
The form can be populated in two methods:
- Page Form: The form will be populated and the hooks are attached, a display directive is generated ngform. You can then use this directive anywhere on your page to print the form.
- Modal Form: The form will be populated and the hooks are attached, however the form uses the Modal feature of AngularJS's Bootstrap and injects its ngform directive in it.
Usage
The Form requires a configuration object that includes the fields and actions it needs to populate. Since the form can be displayed in two methods as explained above, there are two constructors provided to build it. The below table explains the parameters passed on to the form constructors.
Build Form:
Feature | Description |
---|---|
Scope | The scope of the module's controller, refer to Create UI Module for more information. |
Configuration | A configuration object that contains the fields and operations. |
Build Form in Modal:
Feature | Description |
---|---|
Scope | The scope of the module's controller, refer to Create UI Module for more information. |
Modal | An instance of the Modal feature from AngularJS's Bootstrap. |
Configuration | A configuration object that contains the fields and operations. |
//create a form configuration object var config = { "form": { //specify the list of inputs and how they should be rendered "entries": [ { 'name': 'username', 'label': 'Username', 'type': 'text', 'placeholder': 'Enter Username...', 'value': '', 'tooltip': 'Usernames are alphanumeric and support _ & - characters only', 'required': true }, { 'name': 'email', 'label': 'Email', 'type': 'email', 'placeholder': 'Enter Email...', 'value': '', 'tooltip': 'myemail@example.domain', 'required': true } ] }, //give your form a machine name "name": 'addMember', //add a label for your form, it will show in the form's header "label": 'Add New Member', //attach some action buttons to the form "actions":[ { 'type': 'submit', //button type 'label': 'Add Member', //button label 'btn': 'primary', //button class name (AngularJs's Bootstrap) 'action': function(formData) { //operation function, returns the data entered in the form //add your business logic here } }, { 'type': 'reset', 'label': 'Cancel', 'btn': 'danger', 'action': function(formData) { //add your business logic here } } ] }; //call buildForm buildForm($scope, config); //call buildForm buildFormWithModal($scope, $modal, config);
The above code snippets demonstrates how the form configuration should be.
Supported Inputs
The Form supports several types of field rendering displays; field rendering configuration differ to support the different types of how fields could be rendered.
Property Name | Property Type | Description | Supported by Inputs of Type |
---|---|---|---|
type | String | The type of the field, should be one of the values of the forth column | text | password | email | number | phone | url | readonly | textarea | radio | checkbox | select | multi-select | date-picker | html | document | image | audio | video | group | accordion | tabset | buttonSlider |
name | String | Name of the Field | text | password | email | number | phone | url | readonly | textarea | radio | checkbox | select | multi-select | date-picker | html | document | image | audio | video | group | accordion | tabset | buttonSlider |
tabs | Array of Objects | Array of Tab Entries where each entry contains:
| tabset |
description | Object | HTML description associated with angular bootstrap alert directive. Ex: { "type": "info", "content": "input description value..." } | accordion | group | tabset |
icon | string | represents which icon to use from the iconmoon set Ref: https://icomoon.io/#preview-free Ex: <span class="icon icon-{{entry.icon}}"></span> | group |
label | String | Label of the Field | text | password | email | number | phone | url | readonly | textarea | radio | checkbox | select | multi-select | date-picker | html | document | image | audio | video | group | accordion | tabset | buttonSlider |
disabled | Boolean | depicts whether the input is disabled or not | text | password | email | number | phone | url | readonly | textarea | radio | checkbox | select | multi-select | date-picker | html | document | image | audio | video | group | accordion | tabset | buttonSlider |
entries | Array of Objects | Array of Objects, each object represents an input | group | accordion |
required | Boolean | Specify if input is required or not | text | password | email | number | phone | url | readonly | textarea | radio | checkbox | select | multi-select | date-picker | buttonSlider |
fieldMsg | String | Optional text to display below input | text | password | email | number | phone | url | readonly | textarea | radio | checkbox | select | multi-select | date-picker | html | document | image | audio | video | group | accordion | tabset | buttonSlider |
hidden | Boolean | depicts whether the inputs should be displayed in the HTML form entries or not | text | password | email | number | phone | url | readonly | textarea | radio | checkbox | select | multi-select | date-picker | html | document | image | audio | video | group | accordion | tabset | buttonSlider |
placeholder | String | Optional text to by default as input placeholder | text | email | number | phone | url | readonly | textarea |
tooltip | String | Optional text to display in a tooltip above input when mouse is over input | text | password | email | number | phone | url | textarea | radio | checkbox | select | multi-select | date-picker |
rows | integer | Optional number of rows in a textarea | textarea |
min | date | Minimum starting date value | date-picker | number |
limit | integer | Maximum number of uploaded files for the given type or 0 for unlimited | document | image | audio | video |
value | String | The value of the input | text | password | email | number | phone | url | readonly | textarea | html |
value | array | Array of available value and which are selected by default. Ex: [ {"v": "value1", "l": "Value 1", "selected": true}, {"v": "value2", "l": "Value 2"} ] | select | radio | checkbox | multi-select |
value | date | The value of the date picker | date-picker |
onAction | Function | Triggered when User changes the value of the input this function is associated with. Provides a callback that takes:
| text | password | email | number | phone | url | readonly | textarea | radio | checkbox | select | multi-select | date-picker | html | document | image | audio | video | group | accordion | tabset | buttonSlider |
disableRule | Object | Depicts a configuration that gets rendered to an expression and attached to the watcher scope of angular. The expression is associated with to a property in the scope and If matched, this inputs is automatically disabled. Ex: Sample Disable Rule { "name": "createNewVirtualNetwork", "label": "Create New Virtual Network", "type": "buttonSlider", "value": true, "required": true }, { "name": "newVirtualNetworkName", "label": "Virtual Network Name", "type": "text", "disableRule": { "operator": "AND", "fields": [ "!createNewVirtualNetwork" //disable if above is true ] } } The above sample illustrates that if the first entry has the value true, then the second entry is automatically disabled. |
File Handling
The Form Library provides support for 4 media types: Documents - Images - Audio Tracks - Videos.
Media inputs have special treatment in the form library. When provided, every input can have multiple medias, grouped under it.
Declaring a media input:
{ 'name': 'my_files', 'label': 'My Files', 'type': 'document', 'limit': 1, 'value': [] }
The above snippet shows how a media input named my_files of type document with a maximum limit of 1 media is provided to the form library. The above code will result in an input of type file, for the user to browse and select a file to be uploaded.
Modifying an existing media input:
Files should be stored in GridFS and not on the file system, this guarantees that if a service goes down, the data will not be lost.
The form adds 2 event listeners to every value in an existing media input: download - removeFile.
These listeners are used to either call a service API and download the original version of the media or to trigger a remove operation. Therefore when attempting to replace/remove an existing media input, additional information should be supplied.
{ 'name': 'my_files', 'label': 'My Files', 'type': 'document', 'limit': 1, 'value': [ { '_id': '5551aca9e179c39b760f7a1a', 'routeName': '/my_service/files/download', 'headers': { 'soajsauth': 'soajs_authentication_token' }, 'params': { 'env': 'dev' }, 'metadata': { 'mime': 'text/plain' }, 'contentType': 'text/plain', 'filename': 'my_file.txt' } ] }
The above snippet demonstrates how a media input should be provided to the form for editing. The following table explains the entries of every object inside the array:
Property | Description | Computed |
---|---|---|
_id | The id of the file in GridFS. | YES |
routeName | The Service API that should be called to download the original copy of this file. | NO |
headers | Any optional headers that need to be provided when calling the service APIs to either download or remove the file. | NO |
params | Any optional params that need to be provided when calling the service APIs to either download or remove the file. | NO |
metadata | Computed Object by GridFS that contains the mime type information of the file. | YES |
contentType | A computed value by GridFS representing the mimetype of the file | YES |
fileName | A computed value by GridFS representing the mimetype of the file | YES |
Input Examples
The below input types can be used to group other inputs or information together:
- Accordion
- Group
- Tabset
{ "name": "awsInfra", "label": "AWS Infra", "type": "accordion", "collapsed": false, "entries": [...] }
{ "name": "controllers", "label": "SOAJS Controllers", "type": "group", "collapsed": false, "entries": [...] }
{ "type": "tabset", "tabs": [ { "label": "Image", "entries": [...] }, { "label": "Source Code", "entries": [ { "name": "attachConfigRepo", "label": "Attach Config Repository", "type": "buttonSlider", "value": false } ] }, { "label": "Readiness Probe", "entries": [...] } ] }
The below input types can be used for option selection purposes:
- Checkbox
- Radio
- Select
- Multi-select
- UISelect
{ "name": "groups", "label": "Groups", "type": "checkbox", "value": [ { "v": "owners", "l": "Owner Group" } ], "required": false, "fieldMsg": "" }
{ "name": "status", "label": "Status", "type": "radio", "value": [ { "v": "pending", "l": "pendingNew" }, { "v": "active", "l": "active", "selected": true }, { "v": "inactive", "l": "inactive" } ], "required": true, "fieldMsg": "" }
{ "name": "recipe", "label": "Catalog Recipe", "type": "select", "value": [ { "v": "mongoRecipe", "l": "Mongo Recipe", "group": "cluster" }, { "v": "mongoRecipeVM", "l": "Mongo Recipe VM", "group": "cluster" } ], "required": true, "fieldMsg": "" }
{ "name": "deploymentType", "label": "Deployment Type", "type": "uiselect", "value": [ { "v": "container", "l": "container" }, { "v": "vm", "l": "vm" } ], "required": true, "fieldMsg": "Choose the type of deployment" }
The below input types are text editors that allow the user to input blocks of texts:
- JSON Editor - a light editor that verifies JSON text
- CK Editor - a more complex editor alternative with advanced editing features
{ "name": "docker", "label": "Docker Volume", "type": "jsoneditor", "value": "", "required": true, "tooltip": "Enter the docker configuration.", "fieldMsg": "<div class='fieldMsg'>For more info about Docker volumes click <a target='_blank' href='hyperlink URL'>Here</a></div>", "height": 100 }
{ "name": "docker", "label": "Docker Volume", "type": "ckeditor", "value": "", "required": true, "fieldMsg": "<div class='fieldMsg'>For more info about Docker volumes click <a target='_blank' href='hyperlink URL'>Here</a></div>", "height": 100 }
This input type allows the user to create an HTML input.
In the below example the HTML value creates a button. When clicked, this button adds another volume to the stack of volumes.
{ "type": "html", "value": "<input type='button' class='btn btn-sm btn-success f-right' value='Add Volume'/>", "name": "addVolume" }
Below is a snippet of the "onAction" code that can be found in the service or controller of the corresponding UI module.
formConfig[5].tabs[5].entries[0].onAction = function (id, value, form) { $scope.addNewVolume(); };
formConfig[5].tabs[5].entries[0] in the above snippet points to the exact location of the HTML button we previously configured in our UI configuration file, where "addNewVolume()" is a function that adds a new volume to the stack.
Miscellaneous input types:
These are generic and basic input types such as number, date picker, text area, phone number, and readonly (which is a greyed out field that holds a value and cannot be modified).
{ "type": "readonly", "value": "soajs", "name": "category", "label": "Category" }