## Form Data Readme

A "Form Data" object is an immutable js object. It is used to describe a form that will be automatically generated from the object and to validate the inputs to that form.

The intent of a "Form Data" object is to allow easily-reusable forms that correspond to objects defined in the Open Api 3.0 specification. The helper methods for Form Objects are found in the helpers folder.

### UI Generation from forms
The UI for a given form object is generated by the ```getForm``` method in form-data-helpers.js. 

### Validation 
Validation for a given form is handled by the ```checkForErrors``` method in validation-helpers.js

### Files in the /form-objects folder
These files describe a corresponding object in the Open Api specification using the object format. The somenameForm method in these files returns a form object describing an open api object. The somenameObject method takes in a somenameForm object and produces a javascript object that is a valid sub-piece of an open api document.

## Object format
```
  fieldIdentifier: {
    isRequired: boolean,
    updateForm: required function,
    hasErrors: boolean,
    value: required form data object || List of forms || string,
    isValid: optional function
    validationMessage: optional string
    description: optional string,
    name: required string,
    keyValue: optional string,
    options: optional array of strings,
    dependsOn: optional array of strings,
    updateOptions: optional function(dependsOn value)
  }
```

### Properties

#### isRequired
Defaults to false if not specified.
Whether or not the generated form field is required. If isRequired is true, then required field validation will be automatically included.

#### updateForm
A function that updates the form.
```
  (updatedObject, pathToObject) => { 
    // UPDATE the form data object in the parent state
  }
```
#### hasErrors
Defaults to false if not specified.
Used for validation purposes. Whether or not the form object or any children form objects have validation errors. Updated by ```checkForErrors(formData)```. 

### value
The value of the form field (from user input) or a child form object. Form fields will be recursively generated for child form objects. If this value is a list, then a "list control" form will be generated.

#### isValid
Optional function for validation of the value entered in the form field. Should return false if errors were found and true if the field is valid.
``` 
(value) => {
    // Return boolean indicating whether the value is valid.
  }
```
#### validationMessage
Optional validation message that will be shown when the field contains an invalid input.

#### description
Optional description of the form field that will be displayed under the form name.

#### name
The name that will be displayed above the form field.

#### keyValue
If keyValue is provided, then a form will be generated with a keyValue text input on the left and the "value" form input or child form on the right. This form is a "map" (key, value) pair, with keyValue as the user-entered key and value as the user-entered value.

#### options
If options is provided, the generated form field will be a dropdown.

#### dependsOn & updateOptions
*Field with these properties must represent a dropdown. (i.e. have property "options")*

These properties represent a way for a dropdown be conditionally rendered in the UI based on whether a prerequisite field containing necessary information for populating the dropdown options has been filled out.

##### dependsOn
Path to the value the dropdown field depends on. If the value at path ```dependsOn``` is not defined, the dropdown UI for the field will be hidden.

##### updateOptions
Function that will be called on the prerequisite value when the prerequisite value is filled out/selected by the user. 
``` 
(value the field depends on) => {
  // return options for the field based on the value the field
}
```
##### Example:
  "petType" is a dropdown to select a type of pet.
  "breed" is a dropdown to select a breed of that type of pet.

  if "cats" is selected in the pet type drop then the "breed" dropdown will appear with the options 'main coon', 'persian', and 'bengal'.

```
const getOptions = (petType) => {
  switch(petType): 
    case 'dogs':
      return ['golden retreiver', 'pug', 'poodle']
    case 'cats':
      return ['maine coon', 'persian', 'bengal']
    default:
      return []
}

const selectPetBreedForm = (updateForm) => fromJS({
  petType: {
    name: 'Pet Type'
    value: '',
    options: ['dogs', 'cats'],
    updateForm: e => updateForm(e, path.concat(['animalType']))
  },
  breed: {
    name: 'Breed'
    value: '',
    options: [],
    updateForm: e => updateForm(e, path.concat(['breed']))
    dependsOn: ['petType', 'value']
    updateOptions: getOptions
  }
})
```