Enketo has been used all around the world for a wide range of uses from needs assessments in humanitarian aid, to raising historical awareness, to clinical research, to election monitoring.
- Can connect to your custom backend
- Have the edit api in case user wants to edit submitted response
- Api for the customize change in XML of form
- Have beautiful themes and widgets
- Are printer-friendly
- Can use very powerful skip and validation logic
- Run on any device, mobile or desktop, as long as it has a fairly modern browser
Note: Preferable Npm version (6.14.15) and Node version(v14.18.1) and Ubuntu OS version(18.04)*
- Check the node and npm version by running following commands.
node -v
npm -v
You can get your own fork/copy of enketo by using the Fork button.
You need to clone (download) it to a local machine using
git clone https://github.com/Your_Username/enketo.git
This makes a local copy of the repository in your machine.
Once you have cloned the enketo
repository in GitHub, move to that folder first using the change directory command.
# This will change directory to a folder enketo
cd enketo
Move to this folder for all other commands.
Run the following commands to see that your local copy has a reference to your forked remote repository in GitHub
git remote -v
origin https://github.com/Your_Username/enketo.git (fetch)
origin https://github.com/Your_Username/enketo.git (push)
cd enketo-express
docker run --name enketo-redis-main -p 6379:6379 -d redis
docker run --name enketo-redis-cache -p 6380:6379 -d redis
npm install
npm i -g grunt
grunt develop
cd ../enketo-core
npm install
npm start
cd ../enketo-transformer
npm install
npm start
cd ../forms
python3 -m http.server
You can preview your form on http://localhost:8005/preview?xform=http://localhost:8080/getForm/SOE
Customize the submission url with your hosted backend.
- Encrypting query parameters on rendering the enketo form.
- Writing a API for changing an XML form directly from it.
- add npm scripts for install
We are trying to an inversion of control here.
curl --location --request GET 'http://localhost:3002/form/form2'
curl --location --request POST 'http://localhost:3002/prefill' \
--header 'Content-Type: application/json' \
--data-raw '{
"prefillSpec": {
"pf_name": "`${onFormSuccessData.name}`",
"pf_iti": "`${onFormSuccessData.itiByIti.name}`",
"pf_trade": "`${onFormSuccessData.tradeName}`",
"pf_batch": "`${onFormSuccessData.batch}`",
"pf_industry": "`${onFormSuccessData.industryByIndustry.name}`",
"ojt_month": "`${onFormSuccessData.industryByIndustry.schedules[0].is_industry === true ? 1 : 0}`"
},
"onFormSuccessData": {
"name": "DEVA",
"batch": "2021-2023",
"id": 8,
"DOB": "2005-03-04",
"affiliationType": "NCVT",
"registrationNumber": "ICA211021569832",
"tradeName": "Electrician",
"iti": 7,
"industry": 1,
"itiByIti": {
"id": 7,
"name": "GITI Nagina"
},
"industryByIndustry": {
"id": 1,
"name": "Kaushal Bhawan",
"latitude": 30.695753,
"longitude": 76.872025,
"schedules": [
{
"is_industry": true
}
]
}
},
"form": "form2"
}'
Example config
{
"start": "form1",
"forms": {
"form1": {
"skipOnSuccessMessage": true,
"prefill": {},
"submissionURL": "http://esamwad.samagra.io/api/v4/form/submit",
"name": "SampleForm",
"successCheck": "async (formData) => { console.log('From isSuccess', formData.getElementsByTagName('reg_no')[0].textContent); return formData.getElementsByTagName('reg_no')[0].textContent === 'registration123'; }",
"onSuccess": {
"notificationMessage": "Form submitted successfully or not Maybe",
"sideEffect": "async (formData) => { return JSON.parse(decodeURIComponent('%7B%0A%20%20%20%20%20%20%20%20%22name%22%3A%20%22DEVA%22%2C%0A%20%20%20%20%20%20%20%20%22batch%22%3A%20%222021-2023%22%2C%0A%20%20%20%20%20%20%20%20%22id%22%3A%208%2C%0A%20%20%20%20%20%20%20%20%22DOB%22%3A%20%222005-03-04%22%2C%0A%20%20%20%20%20%20%20%20%22affiliationType%22%3A%20%22NCVT%22%2C%0A%20%20%20%20%20%20%20%20%22registrationNumber%22%3A%20%22ICA211021569832%22%2C%0A%20%20%20%20%20%20%20%20%22tradeName%22%3A%20%22Electrician%22%2C%0A%20%20%20%20%20%20%20%20%22iti%22%3A%207%2C%0A%20%20%20%20%20%20%20%20%22industry%22%3A%201%2C%0A%20%20%20%20%20%20%20%20%22itiByIti%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22id%22%3A%207%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%20%22GITI%20Nagina%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22industryByIndustry%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22id%22%3A%201%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%20%22Kaushal%20Bhawan%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22latitude%22%3A%2030.695753%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22longitude%22%3A%2076.872025%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22schedules%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22is_industry%22%3A%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D')); }",
"next": {
"type": "form",
"id": "form2"
}
},
"onFailure": {
"message": "Form submission failed",
"sideEffect": "async (formData) => { console.log(formData); }",
"next": {
"type": "url",
"id": "google"
}
},
"metaData": {
"constant1": "Test"
}
},
"form2": {
"skipOnSuccessMessage": true,
"prefill": {
"pf_name": "`${onFormSuccessData.name}`",
"pf_iti": "`${onFormSuccessData.itiByIti.name}`",
"pf_trade": "`${onFormSuccessData.tradeName}`",
"pf_batch": "`${onFormSuccessData.batch}`",
"pf_industry": "`${onFormSuccessData.industryByIndustry.name}`"
},
"submissionURL": "http://esamwad.samagra.io/api/v4/form/submit",
"name": "SampleForm",
"successCheck": "async (formData) => { console.log('From isSuccess', formData.getElementsByTagName('reg_no')[0].textContent); return formData.getElementsByTagName('reg_no')[0].textContent === 'registration123'; }",
"onSuccess": {
"message": "Form submitted successfully",
"sideEffect": "async (formData) => { console.log(formData); }",
"next": {
"type": "form",
"id": "form2"
}
},
"onFailure": {
"notificationMessage": "Form submission failed",
"sideEffect": "async (formData) => { console.log(formData); }",
"next": {
"type": "url",
"id": "https://google.com"
}
},
"metaData": {
"constantForm2": "Test"
}
}
},
"urls": {
"google": {
"url": "https://google.com",
"queryParams": {},
"onSuccess": {
"message": null,
"sideEffect": "async (formData) => { console.log(formData); }",
"next": null
}
}
},
"metaData": {}
}
State for prefilling, sideEffect.
{
"onFormSuccessData": {},
"formConfig": {},
"formState": {},
}
TODO: Add details on the specifications
- XSS (High Priority) - Simple form
- SQL Injection (High Priority) - needs to be fixed.