npm package: @financial-times/ip-forms-hbs
Description: create forms from json using handlebars
Author: Internal Products
Latest version: 0.0.1
Deprecated: This package is no longer supported

# ip-forms-hbs

[![npm version](https://badge.fury.io/js/%40financial-times%2Fip-forms-hbs.svg)](https://badge.fury.io/js/%40financial-times%2Fip-forms-hbs) 
[![CircleCI](https://circleci.com/gh/Financial-Times/ip-forms-hbs/tree/master.svg?style=svg&circle-token=80cb4430ea94c24f45e7c8b2ea379fca821710ee)](https://circleci.com/gh/Financial-Times/ip-forms-hbs/tree/master)

This module provides handlebar partials that will allow you to create a form with different question types such as radio buttons, checkboxes, text fields, select boxes etc based on a json or yaml file that you provide.

## Setup
```javascript

  npm install -S @financial-times/ip-forms-hbs

```
## Usage
In order to start using the handlebars partials provided by the module, you need to register them as partials first. This can be done in different ways depending on the configuration that you prefer. Below you can find two ways of registering the modules's partials - one is using handlebars and the other is using express-handlebars. 

**N.B**: The partials in the module have an extension of html. So specify this while registering your partials.

```javascript

  //using handlebars
  const handlebars = require('handlebars');
  const viewsPath = join(__dirname, 'node_modules/@financial-times/ip-forms-hbs/views/partials');
  const viewsPattern = join(viewsPath, '**', '*.html');
  const partials = glob(viewsPattern)
    .map(file => ({
      name: join(relative(viewsPath, parse(file).dir), parse(file).name),
      file: read(file).toString(),
    }))
    .reduce((partial, { name, file }) => ({ ...partial, [name]: file }), {});
  handlebars.registerPartial(partials);

  //using express-handlebars
  const exphbs = require('express-handlebars');
  const handlebars = exphbs.create({ extname: '.html', partialsDir:['views/partials/',
                    'node_modules/@financial-times/ip-forms-hbs/views/partials']});

```

You can provide data to the partials in two different ways:

```javascript
  // Option 1 : provide a json data that is formated in a way that the module expects 
  // - example is provided at Sample Data section below
  const data = require('./exampleData.json');
  
  // Option 2 : use the 'formatData' method of the module with yaml data, example given below, 
  // which will convert it to a json data that is in a format that the module expects
  const {formatData} = require('@financial-times/ip-forms-hbs');
  const yamlData = fs.readFileSync('pathToYourYamlFile', 'utf8');
  const data = formatData(yamlData);  
```

All the behaviours needed for the form field to function properly is provided as a single script file, main.js, and you need to include it in your script file as it is or require it if you are using a build tool to bundle your scripts as:
```javascript
require('@financial-times/ip-forms-hbs/public/main.js');
```

Once all the setup is done, use the _**form**_ partial in your app's handlebar template as:
```
...
  <div>
  {{> form }} 
  </div>
...
```
## Question Types 
- **Binary** - for creating radio input fields with the given options as their value
- **long-text** - for creating a textarea input field
- **text** - for creating text input fields
- **checkbox** - for creating checkbox input fields with the given options as their value
- **select-box** - for creating a drop-down list with the given options as available options in the list.
- **upload** - for creating input field with a type of file for uploading files

## Sample Data
To properly construct your form it is advisable that you construct the questions in the following yaml format and use _formatData(yamlFile)_ method to convert it to a json format and pass that to the template. Additionally, if you have values that you want to include as part of the form but want it to be hidden from the user, you can include these values as shown below and the module will include them to the form as input fields with type hidden.

<br> YAML File
```yaml
name: abc
method: POST
title: ip-forms-hbs
enctype: multipart/formdata
action: ""
description: |
 We believe in happy customers.
hidden:
 - fieldName: surveyId
   value: cust-sat-001
 - fieldName: region
   value: West-EU
sections:
 - title: Customer Satisifaction
   form:
   - question: Are you satisfied with our service?
     type: binary
     options:
        - Yes
        - No
   - question: What service of ours do you use most?
     type: checkbox
     options: 
        - Email Service
        - Data Service
        - Chatbot services
        - Sign Up
        - Others
     when:
      question: Are you satisfied with our service?
      is : Yes
   - question: How well do our products meet your needs?
     type: text
   - question: How long have you been a customer of our company?
     type: select-box
     options: 
      - less than 6 months
      - 6 months to one year
      - 1-2 years
      - 3 years or more
   - question: Please upload a copy of your contract with us.
     type: upload
   - question: Do you have any other comments, questions or concerns?
     type: long-text
      
```

<br>JSON Data
```json
{
  "name": "abc",
  "method": "POST",
  "title": "ip-forms-hbs",
  "enctype": "multipart/formdata",
  "action": "",
  "description": "We believe in happy customers.",
  "hidden": [
        {
            "fieldName": "surveyId",
            "value": "cust-sat-001"
        },
        {
            "fieldName": "region",
            "value": "West-EU"
        }
    ],
  "sections": [
    {
      "title": "Customer Satisifaction",
      "form": [
        {
          "question": "Are you satisfied with our service?",
          "type": "binary",
          "options": [
            "Yes",
            "No"
          ],
          "id": 0
        },
        {
          "question": "What service of ours do you use most?",
          "type": "checkbox",
          "options": [
            "Email Service",
            "Data Service",
            "Chatbot services",
            "Sign Up",
            "Others"
          ],
          "when": {
            "question": "Are you satisfied with our service?",
            "is": "Yes"
          },
          "id": 1,
          "parent-id": 0
        },
        {
          "question": "How well do our products meet your needs?",
          "type": "text",
          "id": 2
        },
        {
          "question": "How long have you been a customer of our company?",
          "type": "select-box",
          "options": [
            "less than 6 months",
            "6 months to one year",
            "1-2 years",
            "3 years or more"
          ],
          "id": 3
        },
        {
          "question": "Please upload a copy of your contract with us.",
          "type": "upload",
          "id": 4
        },
        {
          "question": "Do you have any other comments, questions or concerns?",
          "type": "long-text",
          "id": 5
        }
      ]
    }
  ]
}
```

## Styling
Setup your bowerrc file as described at https://registry.origami.ft.com/components and add the following origami components to your project.
- o-forms
- o-typography
- o-buttons

Finally, you also need to include the following styling to your app's stylesheet, *.scss, file to make the partials work properly.

```scss
.o-forms__label--child-questions {
  padding: 10px 0;
  display: none;
}
.form-question {
  position: relative;
  padding: 10px;
  background: oColorsGetPaletteColor('black-5');
  margin: 10px 0;
}
.salvation {
  @include oTypographySans(-2);
  opacity: 0;
  transition: opacity 0.3s linear;
  position: absolute;
  left: 90%;
  margin-left: 10px;
}
```

## Licence
   MIT