-
Notifications
You must be signed in to change notification settings - Fork 2
Akvo React Form
Simple react component for building webforms. View Demo
npm install --save akvo-react-form
yarn add akvo-react-form
Type | Description |
---|---|
input | Input |
number | InputNumber |
cascade | Cascade Select |
text | TextArea |
date | Date |
option | Option |
multiple_option | Multiple Select |
tree | Tree Select |
table | Table (Multiple Question) |
autofilled | Autofilled |
image | Image |
import React from 'react';
import 'akvo-react-form/dist/index.css'; /* REQUIRED */
import { Webform } from 'akvo-react-form';
import * as forms from './example.json';
const App = () => {
const onChange = ({ current, values, progress }) => {
console.log(progress);
};
const onFinish = (values, refreshForm) => {
console.log(values);
};
return (
<div className="full-width">
<Webform
forms={forms.default}
onChange={onChange}
onFinish={onFinish}
/>
</div>
);
};
export default App;
If using the autosave parameter, a form refresh is required to remove traces of the previous fields.
onFinish
includes a function to do this, you also need to change the autosave parameter if the submission is successful. If not, the form refresh will clean up the current datapoint.
Props | Description | Type | Default |
---|---|---|---|
sidebar | Option to show / hide sidebar | Boolean | true |
sticky | Sticky header and sidebar (Not support for IE9) | Boolean | false |
onFinish | Trigger after submitting the form and verifying data successfully | function(values) |
- |
onChange | Trigger after field value changed | function({current,values,progress}) |
- |
onCompleteFailed | Trigger when submit is clicked with blank required question | function(values, errorFields) |
- |
submitButtonSetting | Submit Button Setting | Object{loading: Boolean, disabled: Boolean} | undefined
|
{} |
extraButton | Extra Button Next to Submit Button | ReactComponent | undefined
|
- |
initialValue | Set value by Form initialization | Array[Initial Value] | undefined
|
Array[] |
printConfig | Support survey print functionality | Object{showButton: Boolean, filename: String, hideInputType: Array["field type"], header: ReactComponent} | undefined
|
- |
downloadSubmissionConfig | Support download submission to Excel | Object{visible: Boolean, filename: String, horizontal: Boolean} | undefined
|
- |
leftDrawerConfig | Show left drawer with custom component | Object{visible: Boolean, title: String, Content: ReactComponent} | undefined
|
- |
autoSave | Enable auto save to IndexedDB |
autoSaveObject | undefined
|
- |
fieldIcons | Show icon for input and number question type | Boolean | true |
formRef | Set react useRef for Form from host |
React useRef
|
null |
languagesDropdownSetting | Languages Dropdown Setting | Object{showLanguageDropdown: Boolean , languageDropdownValue: ISO 639-1 codes} | undefined
|
{} |
Props | Description | Type |
---|---|---|
Unique{any} | Object to be translated | Object{any} |
language | Language | Enum[ISO 693-1] |
Props | Description | Type |
---|---|---|
name | Form Name / Title | String |
question_group | List of Question Group | Array[Question Group] |
Unique{any} | Cascade definition, can be any properties | Array[Cascade] |
languages | List of available languages | Array[enum[ISO 639-1]] | undefined
|
defaultLanguage | Default active language | Enum[ISO 639-1]] | undefined
|
translations | List of translations | Array[Translations] | undefined
|
Props | Description | Type |
---|---|---|
name | Question Group Name / Title | String |
order | Question Group Order | Integer | undefined
|
description | Question Group Description | String | undefined
|
question | List of Question | Array[Question] |
translations | List of translations | Array[Translations] | undefined
|
Cascading select questions are sets of questions whose options depend on the response to a previous question. Cascade object should be pre-defined on the question definition root object itself.
Props | Description | Type |
---|---|---|
value | Cascade Value | Unique (Integer | String) |
label | Cascade Label | String |
children | Children of current object | Array[Cascade] | undefined
|
translations | List of translations | Array[Translations] | undefined
|
Example:
{
"name": "Community Culinary Survey 2021",
"translations": [
{
"name": "Komunitas Kuliner Survey 2021",
"language": "id"
}
],
"languages": ["en", "id"],
"question_group": [
{
"name": "Registration",
"order": 1,
"translations": [
{
"name": "Registrasi",
"language": "id"
}
],
"question": [
{
"id": 1,
"name": "Location",
"order": 1,
"type": "cascade",
"option": "administration",
"required": true,
"translations": [
{
"name": "Lokasi",
"language": "id"
}
]
}
]
}
],
"cascade": {
"administration": [
{
"value": 1,
"label": "Jawa Barat",
"children": [
{
"value": 1,
"label": "Garut"
}
]
}
]
}
}
Cascading select also support for a chain API call for the cascade dropdown list.
Props | Description | Type |
---|---|---|
endpoint | Cascade API | String |
initial | Initial Parameter | Integer | String | undefined
|
list | Object name of array |
res.data?.[list] | res.data | String | undefined
|
Example:
"name": "Community Culinary Survey 2021",
"question_group": [{
"name": "Registration",
"order": 1,
"question": [{
"id": 1,
"name": "Location",
"order": 1,
"type": "cascade",
"api": {
"endpoint": "https://tech-consultancy.akvo.org/akvo-flow-web-api/cascade/seap/cascade-296940912-v1.sqlite/",
"initial": 0,
"list": false
},
"required": true
}]
}]
Props | Description | Type |
---|---|---|
id | Cascade Value | Unique (Integer | String) |
name | Cascade Label | String |
API Example : https://tech-consultancy.akvo.org/akvo-flow-web-api/cascade/seap/cascade-296940912-v1.sqlite/0
[
{
"code": "ACEH",
"id": 47,
"name": "ACEH",
"parent": 0
},
{
"code": "BALI",
"id": 128,
"name": "BALI",
"parent": 0
}
]
Props | Description | Type |
---|---|---|
id | Question ID | Unique (Integer | String) |
order | Question Order | Integer | undefined
|
tooltip | Question Tooltip | String | undefined
|
type | Question Type |
number | input | text | option | multiple_option | cascade | tree | autofilled | table | image
|
option | List of Option (for option type of question ) | Array[Option] | String (cascade object name, only for 'cascade' type) | undefined
|
columns | Columns of table (for table type question) question | Array[Columns] | undefined
|
dependency | List of Question Dependency | Array[Dependency] | undefined
|
rule | Question rule to be validated (Only for 'number' type of question) | {min: Integer, max: Integer} |
meta | Question set to be used as data point name | Boolean | undefined
|
required | Set field as required | Boolean | undefined
|
requiredSign | Set custom required field symbol/mark before question label. requiredSign content will show if required param set to true
|
ReactComponent | String | undefined
|
partialRequired | Set a custom required rule for type cascade. Set true to fill without having to select all the cascade level options when the required param is true
|
Boolean | undefined
|
translations | List of translations | Array[Translations] | undefined
|
extra | Extra Component | Array[ExtraComponent] | undefined
|
addonBefore | Addon before Field (only support for number and input type of question) | ReactComponent | String | undefined
|
addonAfter | Addon before Field (only support for number and input type of question) | ReactComponent | String | undefined
|
allowOther | Allow other field (support for option and multiple_option type of question) | Boolean | undefined
|
allowOtherText | Text Replacement for allow other field (support for option and multiple_option type of question) | String | undefined
|
checkStrategy | The way show selected item in box when question type is tree. Default: show checked treeNodes (just show parent treeNode), "children": show only children node |
parent | children | undefined
|
expandAll | Whether to expand all treeNodes by default. Default: false
|
Boolean | undefined
|
fn | Function for autofilled type of question |
Autofilled Object | undefined
|
limit | Set limit / maximum file size in Megabyte (MB) for image type of question | Integer | undefined
|
Props | Description | Type |
---|---|---|
content | Content of the Extra Component | ReactComponent | String |
placement | Placement for the Extra Component |
before | after
|
translations | List of translations | Array[Translations] | undefined
|
Rule should be defined as object, currently we only support min max value for number type of question.
Props | Type |
---|---|
min | Integer | undefined
|
max | Integer | undefined
|
allowDecimal | Boolean | undefined
|
Example:
{
"id": 1,
"name": "Weight",
"order": 1,
"type": "number"
"required": true,
"tooltip": {"text": "Information Text"},
"rule": {"min": 5,"max": 10},
"addonAfter": "Kilograms",
"meta": true,
"translations": [{
"name": "Berat Badan",
"language": "id"
}
],
"extra": [{
"placement": "before",
"content": "Extra Component before the question",
"translations": [{
"content": "Komponen Tambahan sebelum pertanyaan ini",
"language": "id"
}]
}]
}
If question has dependency, question will be hidden by default. The question will only shows when dependency question values matches with the dependency rules.
Props | Description | Type |
---|---|---|
id | Question ID | Integer | String |
options | List of dependency options to be validated, for 'option' type of the dependency question | Array[String] | undefined
|
min | Minimum dependency value to be validate, for 'number' type of the dependency question | Array[String] | undefined
|
max | Maximum dependency value to be validate, for 'number' type of the dependency question | Array[String] | undefined
|
equal | Dependent answer is equal to | Integer | String | undefined
|
notEqual | Dependent answer is not blank and not equal to | Integer | String | undefined
|
Example:
{
"id": 11,
"name": "Where do you usually order Rendang from ?",
"dependency": [
{
"id": 9,
"options": ["Yes"]
},
{
"id": 10,
"min": 8
}
],
"order": 5,
"type": "option",
"option": [
{
"name": "Pagi Sore",
"order": 1
},
{
"name": "Any Rendang Restaurant",
"order": 2,
"translations": [
{
"name": "Restoran Rendang Manapun",
"language": "id"
}
]
}
],
"required": true,
"translations": [
{
"name": "Dimana anda biasanya membeli Rendang?",
"language": "id"
}
]
}
Option is valid only for option
type of question
Props | Description | Type |
---|---|---|
name | Option Name / Label | String |
order | Question Group Order | Integer | undefined
|
translations | List of translations | Array[Translations] | undefined
|
Columns is valid only for table
type of question
Props | Description | Type |
---|---|---|
name | Column / Question object key | String |
type | Column / Question Type |
number | input | text | option
|
label | Column / Question Label | String |
option | Option value | Array[Option] | undefined
|
Props | Description | Type |
---|---|---|
question | Question ID | Unique (Integer | String) |
value | Value of the Question | String | Integer | Object{lat,lng} | Array[Integer | String] | Date Format |
repeatIndex | Repeat Index in Repeated Question Group. Default: 0 | Integer | undefined
|
Example: Initial Value Example
Props | Description | Type |
---|---|---|
fnString | String of function | String |
multiline | Wether function is multiline or not | Bool | undefined
|
Example for fnString:
function () { return #1 / #2 }
OR
() => { return #1.includes("Test") ? #2 / #3 : 0 }
Prefix #N is use to indicate the value of question id N. Note that we don't use javascript eval to overcome the security issue, the function will be sanitized before it's executed.
Props | Description | Type |
---|---|---|
formId | Required | Integer |
name | Name for datapoint | String | undefined
|
buttonText | Custom text for save button | String | undefined
|
Auto save object require formId
when it's enabled. This will filter list of saved data for particular formId
. To show the list of saved datapoint we can use dataStore.
Example:
import React, { useState, useEffect } from 'react'
import { dataStore } from 'akvo-react-form'
const DataList = () => {
const [datapoint, setDatapoint] = useState([])
useEffect(() => {
const listData = dataStore.list(formId)
listData.then((x) => {
setDatapoint(x)
})
}, [])
return (
<table>{dataPoints.map((x, xi) => (
<tr key={xi}>
<td>
{xi + 1}. {x.name}
</td>
<td>
<button onClick={x.load}>
Load
</button>
<button onClick={x.remove}>
Delete
</button>
</Space>
</td>
</tr>
))}
</table>)
}
Please check the Form Definition Example which contains all the current features of akvo-react-form.
AGPL-3.0 © akvo