# How to add a new field type to `fc-form-field`

1. Add a new `.js` file under `src/fields/<fieldTypeName>/<fieldTypeName>-field.js`
    
    Example:
    `src/fields/my-green-select/my-select-field.js`

2. File should expose a render function with following format:
    `render_<fieldTypeName> = funciton () {...}`
    
    Example:
    ```javascript
    import { html } from 'lit-element';
    
    export const render_my_green_select = function() {
        return html`<div>hello world</div>`; // the rendered html of the field
    }
    ```
3. Add the new type name to `fc-form-field-helper.js` under the `FIELD_TYPES` enum object:
    ```javascript
    export const FIELD_TYPES = {
      TAGS: 'tags',
      MY_GREEN_SELECT: 'my-green-select'
    }
    ```

4. Import and call the render method on `FcFormField.js` in `renderField` method with `.call(this);` extension.
    Using `.call(this)` will make sure the render method share same `this` context and have access to the field element.
    
    Example:
    ```javascript
    switch (type) {
            case FIELD_TYPES.TAGS:
              return render_tags.call(this);
            case FIELD_TYPES.TEXT:
              return render_input.call(this);
            case FIELD_TYPES.MY_GREEN_SELECT:
              return render_my_green_select.call(this);
    ```

5.  Add the type of the `type` property jsdoc:
    ```javascript
      /**
       * Type of the field - can be existing types such as: text, number, tags, dropdown or name of the type in the 'custom-renderers' object passed to fc-form.
       * @type {'my-green-select'|'text'|'tags'|'number'|'dropdown'|'date'|'button-group'}
       * @attr
       */
      @property({ type: String }) type = 'text';
    ```

6. Open http://localhost:9001/?path=/story/containers-formfield--type-my-green-select
    
    You will see the naive form field implementation yielding `hello world` to the DOM.
 
7. Implement the render function:
    ### We distinguish between two different field types:
    
    #### Single Value field type
    
    A field type that can only have ONE selected value.
    
    Can be from a list of `options` or without a list.
    
    Examples for such types:
    - `date`
    - `text`
    - `number`
    - `select`
    
    We will use the `my-green-select` for this example.
    
    7.1 Implement your render function with a `<select>` HTML tag:
    ```javascript
    export const render_my_green_select = function() {
        return html`
        <select style="background-color: greenyellow">
          <option>Select An animal</option>
          <option value="dog">Dog</option>
          <option value="cat">Cat</option>
          <option value="mouse">Mouse</option>
        </select>
        `;
    }
    ``` 
   This will draw a simple select.
   
   7.2 Use the `value` property to mark the selected value:
   ```javascript
    export const render_my_green_select = function() {
        const {value} = this;
        return html`
        <select style="background-color: greenyellow">
          <option .selected="${!value}">Select An animal</option>
          <option value="dog" .selected="${value === 'dog'}">Dog</option>
          <option value="cat" .selected="${value === 'cat'}">Cat</option>
          <option value="mouse" .selected="${value === 'mouse'}">Mouse</option>
        </select>
        `;
    }
    ```
   This way we can use following markup:
   ```html
    <fc-form-field type="my-green-select" value="dog"></fc-form-field>
   ```
   That will render the field with `dog` as preselected value.
   
   7.3 Use `this.setValue(...)` to propagate the value to `<fc-form>` container.
   ```javascript
    export const render_my_green_select = function() {
        const {value} = this;
        return html`
        <select style="background-color: greenyellow" 
                @change="${(event) => this.setValue(event.target.value)}">
          <option .selected="${!value}">Select An animal</option>
          <option value="dog" .selected="${value === 'dog'}">Dog</option>
          <option value="cat" .selected="${value === 'cat'}">Cat</option>
          <option value="mouse" .selected="${value === 'mouse'}">Mouse</option>
        </select>
        `;
    }
    ``` 
   
   7.4 Load options from `options` property:
   ```javascript
    export const render_my_green_select = function() {
        const {value, options} = this;
        return html`
        <select style="background-color: greenyellow" 
               @change="${(event) => this.setValue(event.target.value)}">
          <option .selected="${!value}">Select</option>
          ${options.map(option => {
              return html`<option value="${option}" .selected="${value === option}">${option}</option>`
          })}
        </select>
        `;
    }
    ```
   
     This way we can use following markup:
     ```html
      <fc-form-field type="my-green-select" value="dog" options="['cat', dog', 'mouse']"></fc-form-field>
     ```
     That will render the field from the `options` list.
   
    7.5 Clear the value using `this.setValue(null)`:
    ```javascript
    export const render_my_green_select = function() {
        const {value, options} = this;
        return html`
           <select style="background-color: greenyellow" 
               @change="${(event) => {
                   if (event.target.value === 'clear') {
                       this.setValue(null);
                   } else {
                       this.setValue(event.target.value);
                   }
               }}">
             <option value="clear" .selected="${!value}">Select</option>
             ${options.map(option => {
            return html`<option value="${option}" .selected="${value === option}">${option}</option>`
            })}
         </select>`;
    }
   ```
   
   7.6 Use `placeholder`, `disabled`, and `clearable` properties:
    ```javascript
        export const render_my_green_select = function() {
        const {value, options, placeholder, disabled, clearable} = this;
        return html`
           <select .disabled="${ifDefined(disabled)}" style="background-color: greenyellow" 
               @change="${(event) => {
                   if (this.disabled) return;
                   if (event.target.value === 'clear') {
                       this.setValue(null);
                   } else {
                       this.setValue(event.target.value);
                   }
               }}">
             ${clearable ? html`<option value="clear" .selected="${!value}">${placeholder || 'Select'}</option>` : ''}
             ${options.map(option => {
            return html`<option value="${option}" .selected="${value === option}">${option}</option>`
            })}
         </select>`;
    }
   ```
   
   7.7 Add an example to `FcForm.js` to test the new field:
   ```javascript
      <!-- Sample: my cool green selection -->
     
      <fc-form>
          <label>Register new Dog</label>
          <fc-form-section>
              <fc-form-field type="text" path="dog.name" label="dog name" placeholder="Enter dog name.."></fc-form-field>
              <fc-form-field
                   type="my-green-select"
                   placeholder="whats the dog type?"
                   options='["terrier", "labrador", "german shepherd"]'
                   path="dog.type"
                   label="Dog Type">
              </fc-form-field>
          </fc-form-section>
      </fc-form>
    ```

