# Icarus
Icarus is a frontend for the rendering, validation, and submission of forms created by the [Apollo forms backend](https://github.com/Morgan-and-Morgan/ftp-forms-backend).

### Dependencies
In an effort to let Icarus fly, it has no hard dependencies except LoDash. Just don't soar too close to the sun.

### Size
< 40Kb

### Installation
```
yarn add icarus-forms
===
OR
===
npm install --save icarus-forms
===
OR
===
<script type="text/javascript" src="/path/to/icarus.min.js"></script>
```

Then:
```
let Icarus = require('icarus-forms');
// OR
var Icarus = window.Icarus;
```

### Usage
```
let Icarus = require('icarus-forms');

// render a form into the '#icarus-container' container
let form = new Icarus('#icarus-container', {
  apollo: 'apollo.yourdomain.com', // the URL of the apollo forms backend
  formId: 132
});
```

It's also possible to set global defaults on the `Icarus` object to have them apply to every new form instance created
```
let Icarus = require('icarus-forms');

Icarus.setDefaults({
  apollo: 'apollo.yourdomain.com'
});

// this form will use the apolloUrl 'apollo.yourdomain.com' because that is the icarus default.
let form = new Icarus('#icarus-container', {
  formId: 132
});
```

### Options
Icarus supports the following options

| Option        | Default   | Description                                                                                                        |
| ------------- | --------- | -------------------------------------------------------------------------------------------------------------------|
| apollo        | ''        | The location of the apollo forms backend service                                                                   |
| apiRoot       | '/api/v1' | The path to the mount point for the REST API                                                                       |
| formId        | ''        | The ID of the apollo form to render                                                                                |
| theme         | 'default' | The theme to use when rendering the form. See the 'themes' directory for options.                                  |
| themesLocation| ''        | The location of the themes. See [here](https://morgan-and-morgan.github.io/icarus/#themesLocation) for detail      |
| render        | {}        | Render specific options. See [here](https://morgan-and-morgan.github.io/icarus/#render) for detail                 |
| validation    | {}        | Validation specific options. See [here](https://morgan-and-morgan.github.io/icarus/#validation) for detail         |
| listeners     | {}        | Hooks into the lifecycle of the form. See [here](https://morgan-and-morgan.github.io/icarus/#listeners) for detail |

### Gotchas / Notes

1. Binding listeners directly to events on form fields likely won't behave as you expect it to, this due to the way field rendering works.
For instance, say we render a form having three fields: "litigation", "litigation_selector", and "email", the DOM markup looking like:

```html
<div id="form-selector">
    <div class="icarus">
        <form class="icarus-form">
            <div class="icarus-layout">
                <div class="icarus-layout-static">
                    <div class="icarus-field field-email label-vertical required" data-field-id="1">
                        <input type="text" name="email" placeholder="Email" />
                    </div>
                    
                    <div class="icarus-field field-litigation_selector label-vertical required" data-field-id="2">
                        <select name="litigation_selector">
                            <option value="Personal Injury">Personal Injury</option>
                            <option value="Contract Dispute">Contract Dispute</option>
                        </select>
                    </div>
                    
                    <div class="icarus-field field-litigation label-vertical required" data-field-id="3">
                        <input type="hidden" name="litigation" />
                    </div>
                </div>    
            </div>
            
            <button type="submit" class="submit-btn">Submit Evaluation</button>
        </form>
    </div>
</div>
```

Now, say we want to listen to the `change` event of the `litigation_selector`, updating the `litigation` with the selected
value. You would be tempted to do something like:

```javascript
$('#form-selector').on('change', '.field-litigation_selector select', (evt) => {
    $('#form-selector .field-litigation input').val($(evt.target.value));
});
```

The change event will never fire, this due to the fact that the `litigation_selector` field will re-render itself on change of value,
preventing the bubble-up of the event. Alternatively, you can listen on `focusout` events or bind to the form instead (e.g. `$('form').change`). 