diff --git a/examples.module b/examples.module
index efdf09b..7beb6db 100644
--- a/examples.module
+++ b/examples.module
@@ -41,6 +41,7 @@ function examples_toolbar() {
     'dbtng_example' => 'dbtng_example',
     'email_example' => 'email_example.description',
     'field_example' => 'field_example.description',
+    'fapi_example' => 'fapi_example.description',
     'js_example' => 'js_example.info',
     'node_type_example' => 'config_node_type_example.description',
     'page_example' => 'page_example_description',
diff --git a/fapi_example/fapi_example.info.yml b/fapi_example/fapi_example.info.yml
new file mode 100644
index 0000000..5d9b425
--- /dev/null
+++ b/fapi_example/fapi_example.info.yml
@@ -0,0 +1,7 @@
+name: Form API Example
+type: module
+description: Sample implementations that demonstrate the Drupal Forms API
+package: Example modules
+core: 8.x
+dependencies:
+  - examples
diff --git a/fapi_example/fapi_example.links.menu.yml b/fapi_example/fapi_example.links.menu.yml
new file mode 100644
index 0000000..e0c2916
--- /dev/null
+++ b/fapi_example/fapi_example.links.menu.yml
@@ -0,0 +1,47 @@
+# Define default links for this module.
+fapi_example.description:
+  title: Form API Examples
+  description: Form examples using Drupal Form API.
+  route_name: fapi_example.description
+
+fapi_example.simple_form:
+  title: Simple Form API Example
+  description: A simple form example with submit processing.
+  route_name: fapi_example.simple_form
+  parent: fapi_example.description
+
+fapi_example.input_demo:
+  title: Demo of Common Input Elements
+  description: A form to demonstrate input elements.
+  route_name: fapi_example.input_demo
+  parent: fapi_example.description
+
+fapi_example.state_demo:
+  title: Demo of Form State Binding
+  description: A form to demonstrate binding of form state.
+  route_name: fapi_example.state_demo
+  parent: fapi_example.description
+
+fapi_example.container_demo:
+  title: Container Demo
+  description: A form to demonstrate use of containers.
+  route_name: fapi_example.container_demo
+  parent: fapi_example.description
+
+fapi_example.vertical_tabs_demo:
+  title: VerticalTabs Demo
+  description: A form to demonstrate use of vertical tabs.
+  route_name: fapi_example.vertical_tabs_demo
+  parent: fapi_example.description
+
+fapi_example.ajax_demo:
+  title: Ajax Form Example
+  description: A form to demonstrate use of AJAX.
+  route_name: fapi_example.ajax_demo
+  parent: fapi_example.description
+
+fapi_example.build_demo:
+  title: Build Form Demo
+  description: Demostrates the order of firing of from controller methods.
+  route_name: fapi_example.build_demo
+  parent: fapi_example.description
diff --git a/fapi_example/fapi_example.routing.yml b/fapi_example/fapi_example.routing.yml
new file mode 100644
index 0000000..0bd5953
--- /dev/null
+++ b/fapi_example/fapi_example.routing.yml
@@ -0,0 +1,84 @@
+# This routing.yml file makes both the fapi example description page and the
+# included sample forms available at specific URL's on your site. A route
+# maps a URL path to a controller. For page controllers it defines the
+# function or method that will be called when the page is accessed.  For form
+# controllers the content is determined by the buildForm method defined by the
+# form controller implementation.
+
+# Access to these paths is restricted to users with the permission
+# 'access content'. This is notated as _permission: 'access content'.
+
+# Menu items corresponding to these URLs are defined separately in the
+# fapi_example.links.menu.yml file.
+fapi_example.description:
+  path: 'examples/fapi_example'
+  defaults:
+    _controller:  '\Drupal\fapi_example\Controller\Page::description'
+    _title: 'Form API Examples'
+  requirements:
+    _permission: 'access content'
+
+fapi_example.simple_form:
+  path: 'examples/fapi_example/simple_form'
+  defaults:
+    _form:  '\Drupal\fapi_example\Form\SimpleForm'
+    _title: 'Simple Form API Example'
+  requirements:
+    _permission: 'access content'
+
+fapi_example.input_demo:
+  path: 'examples/fapi_example/input_demo'
+  defaults:
+    _form:  '\Drupal\fapi_example\Form\InputDemo'
+    _title: 'Demo of Common Input Elements'
+  requirements:
+    _permission: 'access content'
+
+fapi_example.state_demo:
+  path: 'examples/fapi_example/state_demo'
+  defaults:
+    _form:  '\Drupal\fapi_example\Form\StateDemo'
+    _title: 'Demo of Form State Binding'
+  requirements:
+    _permission: 'access content'
+
+fapi_example.container_demo:
+  path: 'examples/fapi_example/container_demo'
+  defaults:
+    _form:  '\Drupal\fapi_example\Form\ContainerDemo'
+    _title: 'Container Demo'
+  requirements:
+    _permission: 'access content'
+
+fapi_example.vertical_tabs_demo:
+  path: 'examples/fapi_example/vertical_tabs_demo'
+  defaults:
+    _form:  '\Drupal\fapi_example\Form\VerticalTabsDemo'
+    _title: 'VerticalTabs Demo'
+  requirements:
+    _permission: 'access content'
+
+fapi_example.modal_form:
+  path: 'examples/fapi_example/modal_form'
+  defaults:
+    _form:  '\Drupal\fapi_example\Form\ModalForm'
+    _title: 'Modal Form Example'
+  requirements:
+    _permission: 'access content'
+
+fapi_example.ajax_demo:
+  path: 'examples/fapi_example/ajax_demo'
+  defaults:
+    _form:  '\Drupal\fapi_example\Form\AjaxDemo'
+    _title: 'Ajax Form Example'
+  requirements:
+    _permission: 'access content'
+
+fapi_example.build_demo:
+  path: 'examples/fapi_example/build_demo'
+  defaults:
+    _form:  '\Drupal\fapi_example\Form\BuildDemo'
+    _title: 'Build Form Demo'
+  requirements:
+    _permission: 'access content'
+
diff --git a/fapi_example/src/Controller/Page.php b/fapi_example/src/Controller/Page.php
new file mode 100644
index 0000000..567f92a
--- /dev/null
+++ b/fapi_example/src/Controller/Page.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Controller\Page.
+ */
+
+namespace Drupal\fapi_example\Controller;
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Url;
+
+/**
+ * Simple page controller for drupal.
+ */
+class Page extends ControllerBase {
+  /**
+   * Lists the examples provided by form_example.
+   */
+  public function description() {
+    // These libraries are required to facilitate the ajax modal form demo.
+    $content['#attached']['library'][] = 'core/drupal.ajax';
+    $content['#attached']['library'][] = 'core/drupal.dialog';
+    $content['#attached']['library'][] = 'core/drupal.dialog.ajax';
+    $content['intro'] = [
+      '#markup' => '<p>' . $this->t('Form examples to demonstrate comment UI solutions using the Drupal Form API.') . '</p>',
+    ];
+
+    // Create a bulleted list of links to the form examples.
+    $content['links'] = [
+      '#theme' => 'item_list',
+      '#items' => [
+        $this->l($this->t('Simple Form'), Url::fromRoute('fapi_example.simple_form')),
+        $this->l($this->t('Input Demo'), Url::fromRoute('fapi_example.input_demo')),
+        $this->l($this->t('Form State Example'), Url::fromRoute('fapi_example.state_demo')),
+        $this->l($this->t('Container Demo'), Url::fromRoute('fapi_example.container_demo')),
+        $this->l($this->t('Vertical Tab Demo'), Url::fromRoute('fapi_example.vertical_tabs_demo')),
+        $this->l($this->t('Ajax Demo'), Url::fromRoute('fapi_example.ajax_demo')),
+
+        // The following link is generated by the link Render element.  I used
+        // this so that the appropriate attributes could be set on the link.
+        // the l method doesn't take these parameters.
+        // Attributes are used by the core dialog libraries to invoke the modal.
+        [
+          '#type' => 'link',
+          '#title' => $this->t('Modal Example'),
+          '#url' => new Url('fapi_example.modal_form'),
+          '#attributes' => [
+            'class' => ['use-ajax'],
+            'data-dialog-type' => 'modal',
+            ]
+        ],
+        $this->l($this->t('Build Demo'), Url::fromRoute('fapi_example.build_demo')),
+      ],
+    ];
+
+    // The message container is used by the modal form example it is an empty
+    // tag that will be replaced by content.
+    $content['message'] = [
+      '#type' => 'container',
+      '#attributes' => ['id' => 'fapi-example-message'],
+    ];
+    return $content;
+  }
+
+}
diff --git a/fapi_example/src/Form/AjaxDemo.php b/fapi_example/src/Form/AjaxDemo.php
new file mode 100644
index 0000000..17df9e1
--- /dev/null
+++ b/fapi_example/src/Form/AjaxDemo.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Form\AjaxDemo.
+ */
+
+namespace Drupal\fapi_example\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Implements the ajax demo form controller.
+ *
+ * @see \Drupal\Core\Form\FormBase
+ * @see \Drupal\Core\Form\ConfigFormBase
+ */
+class AjaxDemo extends DemoBase {
+
+  /*
+   * Possible colors to choose from.
+   * Used by colorCallback to determine which colors to include in the
+   * select element.
+   */
+  private $colors = [
+    'warm' => [
+      'red' => 'Red',
+      'orange' => 'Orange',
+      'yellow' => 'Yellow',
+    ],
+    'cool' => [
+      'blue' => 'Blue',
+      'purple' => 'Purple',
+      'green' => 'Green',
+    ],
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+
+    /*
+     * The #ajax attribute used in the temperature input element defines an ajax
+     * callback that will invoke the colorCallback method on this form object.
+     * Whenever the temperature element changes, it will invoke this callback
+     * and replace the contents of the color_wrapper container with the reults of this
+     * method call.
+     */
+    $form['temperature'] = [
+      '#title' => $this->t('Temperature'),
+      '#type' => 'select',
+      '#options' => [ 'warm' => 'Warm', 'cool' => 'Cool'],
+      '#empty_option' => $this->t('-select'),
+      '#ajax' => [
+        // Could also use [ $this, 'colorCallback']
+        'callback' => '::colorCallback',
+        'wrapper' => 'color-wrapper',
+      ]
+    ];
+
+    // Disable caching on this form.
+    $form_state->setCached(FALSE);
+
+    $form['actions'] =[
+      '#type' => 'actions',
+    ];
+
+    // Add a submit button that handles the submission of the form.
+    $form['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Submit'),
+    ];
+
+    //
+    $form['color_wrapper'] = [
+      '#type' => 'container',
+      '#attributes' => ['id' => 'color-wrapper']
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'fapi_example_ajax_demo';
+  }
+
+  /**
+   * Implements callback for Ajax event on color selection.
+   */
+  public function colorCallback(array &$form, FormStateInterface $form_state) {
+    $temperature = $form_state->getValue('temperature');
+
+    // Add a color element to the color_wrapper container using the value
+    // from temparature to determine which colors to include in the select
+    // element.
+    $form['color_wrapper']['color'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Color'),
+      '#options' => $this->colors[$temperature],
+    ];
+
+    return $form['color_wrapper'];
+  }
+
+}
diff --git a/fapi_example/src/Form/BuildDemo.php b/fapi_example/src/Form/BuildDemo.php
new file mode 100644
index 0000000..9999ba3
--- /dev/null
+++ b/fapi_example/src/Form/BuildDemo.php
@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Form\BuildDemo.
+ */
+
+namespace Drupal\fapi_example\Form;
+
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Implements the build demo form controller.
+ *
+ * The form uses drupal_set_message() calls to demonstrate the order of
+ * contoller method invocations by the form api.
+ *
+ * @see \Drupal\Core\Form\FormBase
+ * @see \Drupal\Core\Form\ConfigFormBase
+ */
+class BuildDemo extends FormBase {
+
+  /**
+   * Counter keeping track of the sequence of method invocation.
+   * @var int
+   */
+  static $_sequence = 0;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct() {
+    $this->displayMethodInvocation('__construct');
+  }
+
+  /**
+   * Display the method being called and it's sequence in the form
+   * processing.
+   *
+   * @param $method_name
+   *   The method being invoked.
+   */
+  private function displayMethodInvocation($method_name) {
+    self::$_sequence++;
+    drupal_set_message(self::$_sequence . ". $method_name");
+  }
+
+  /**
+   * Build form demonstration.
+   *
+   * This form demonstrates the different type of build form methods and their
+   * order of invocation.
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+
+    // Simple checkbox for ajax orders.
+    $form['change'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Change Me'),
+      '#ajax' => [
+        'callback' => '::ajaxSubmit',
+        'wrapper' => 'message-wrapper',
+      ],
+    ];
+
+    $form['actions'] = [
+      '#type' => 'actions',
+    ];
+
+    // Add a submit button that handles the submission of the form.
+    $form['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => 'Submit',
+    ];
+
+
+    // Add button handlers.
+    $form['actions']['button'] = [
+      '#type' => 'button',
+      '#value' => 'Rebuild',
+    ];
+
+    $form['actions']['rebuild'] = [
+      '#type' => 'button',
+      '#value' => 'Submit Rebuild',
+      '#submit' => ['::rebuildFormSubmit']
+    ];
+
+    $form['actions']['ajaxsubmit'] = [
+      '#type' => 'submit',
+      '#value' => 'Ajax Submit',
+      '#ajax' => [
+        'callback' => '::ajaxSubmit',
+        'wrapper' => 'message-wrapper',
+      ]
+    ];
+
+    $form['messages'] = [
+      '#type' => 'container',
+      '#attributes' => ['id' => 'message-wrapper']
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    $this->displayMethodInvocation('getFormId');
+    return 'fapi_example_simple_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    $this->displayMethodInvocation('validateForm');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $this->displayMethodInvocation('submitForm');
+  }
+
+  /**
+   * Implements ajax submit callback.
+   *
+   * @param array $form
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   */
+  public function ajaxSubmit(array &$form, FormStateInterface $form_state) {
+    $this->displayMethodInvocation('ajaxSubmit');
+    $form['messages']['status'] = [
+      '#type' => 'status_messages',
+    ];
+
+    return $form['messages'];
+  }
+
+  /**
+   * Implements submit callback for Rebuild button.
+   *
+   * @param array $form
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   */
+  public function rebuildFormSubmit(array &$form, FormStateInterface $form_state) {
+    $this->displayMethodInvocation('rebuildFormSubmit');
+    $form_state->setRebuild(TRUE);
+  }
+
+}
diff --git a/fapi_example/src/Form/ContainerDemo.php b/fapi_example/src/Form/ContainerDemo.php
new file mode 100644
index 0000000..f7db38b
--- /dev/null
+++ b/fapi_example/src/Form/ContainerDemo.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Form\StateDemo.
+ */
+
+namespace Drupal\fapi_example\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Implements the container demo form.
+ *
+ * The submit handler in this form is provided by the DemoBase class.
+ * @see \Drupal\Core\Form\FormBase
+ * @see \Drupal\Core\Form\ConfigFormBase
+ */
+class ContainerDemo extends DemoBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+
+    // Details containers replace D7's collapsible field sets.
+    $form['author'] = [
+        '#type' => 'details',
+        '#title' => 'Author Info (type = details)',
+    ];
+
+    $form['author']['name'] = [
+     '#type' => 'textfield',
+     '#title' => $this->t('Name'),
+    ];
+
+    $form['author']['pen_name'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Pen Name'),
+    ];
+
+    // Conventional field set.
+    $form['book'] = [
+      '#type' => 'fieldset',
+      '#title' => $this->t('Book Info (type = fieldset)'),
+    ];
+
+    $form['book']['title'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Title'),
+    ];
+
+    $form['book']['publisher'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Publisher'),
+    ];
+
+    // Containers have no visual display but wrap any contained elements in a
+    // div tag.
+    $form['accommodation'] = [
+      '#type' => 'container',
+    ];
+
+    $form['accommodation']['title'] = [
+      '#type' => 'html_tag',
+      '#tag' => 'p',
+      '#value' => $this->t('Special Accommodations (type = container)'),
+    ];
+
+    $form['accommodation']['diet'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Dietary Restrictions'),
+    ];
+
+    $form['actions'] = ['#type' => 'actions'];
+    
+    $form['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Submit'),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * @inheritdoc
+   */
+  public function getFormId() {
+    return 'fapi_example_container_demo';
+  }
+
+}
\ No newline at end of file
diff --git a/fapi_example/src/Form/DemoBase.php b/fapi_example/src/Form/DemoBase.php
new file mode 100644
index 0000000..b00bf30
--- /dev/null
+++ b/fapi_example/src/Form/DemoBase.php
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Form\DemoBase.
+ */
+
+namespace Drupal\fapi_example\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Implements common submit handler used in fapi_example demo forms.
+ *
+ * We extend FormBase, which is the simplest form base class used in Drupal, to
+ * add a common submitForm method that will display the submitted values via
+ * drupal_set_message().
+ *
+ * @see \Drupal\Core\Form\FormBase
+ */
+abstract class DemoBase extends FormBase {
+  /**
+   * Implements a form submit handler.
+   *
+   * @param array $form
+   *   The render array of the currently built form.
+   * @param FormStateInterface $form_state
+   *   Object describing the current state of the form.
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    //Find out what was submitted
+    $values = $form_state->getValues();
+    foreach($values  as $key => $value) {
+      $label = isset($form[$key]['#title']) ? $form[$key]['#title'] : $key;
+      // many arrays return 0 for unselected values so lets filter that out.
+      if (is_array($value)) $value = array_filter($value);
+
+      // Only display for controls that have titles and values.
+      if ($value ) {
+        $display_value = is_array($value) ? print_r($value, 1) : $value;
+        $message = $this->t('Value for %title: %value' , ['%title' => $label, '%value' => $display_value]);
+        drupal_set_message($message);
+      }
+    }
+  }
+
+}
diff --git a/fapi_example/src/Form/InputDemo.php b/fapi_example/src/Form/InputDemo.php
new file mode 100644
index 0000000..4eb1dfb
--- /dev/null
+++ b/fapi_example/src/Form/InputDemo.php
@@ -0,0 +1,234 @@
+<?php
+/**
+ * @file
+ *
+ * Contains Drupal\fapi_example\Form\InputDemo
+ */
+
+namespace Drupal\fapi_example\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+
+/**
+ * Class InputDemo
+ * @package Drupal\fapi_example\Form
+ */
+class InputDemo extends FormBase {
+
+  /**
+   * Form Building function.
+   * @param array $form
+   *   Partially built form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   Object representing the state of the form.
+   * @return array
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+
+    // CheckBoxes
+    $form['tests_taken'] = [
+      '#type' => 'checkboxes',
+      '#options' => ['SAT' => t('SAT'), 'ACT' => t('ACT')],
+      '#title' => $this->t('What standardized tests did you take?'),
+      '#description' => 'Checkboxes, #type = checkboxes',
+    ];
+
+    // Color
+    $form['color'] = [
+      '#type' => 'color',
+      '#title' => $this->t('Color'),
+      '#default_value' => '#ffffff',
+      '#description' => 'Color, #type = color',
+    ];
+
+    // Date
+    $form['expiration'] = [
+      '#type' => 'date',
+      '#title' => $this->t('Content expiration'),
+      '#default_value' => ['year' => 2020, 'month' => 2, 'day' => 15,],
+      '#description' => 'Date, #type = date',
+    ];
+
+    // Email
+    $form['email'] = [
+      '#type' => 'email',
+      '#title' => $this->t('Email'),
+      '#description' => 'Email, #type = email',
+    ];
+
+    // Number
+    $form['quantity'] = [
+      '#type' => 'number',
+      '#title' => t('Quantity'),
+      '#description' => $this->t('Number, #type = number'),
+    ];
+
+    // Password
+    $form['password'] = [
+      '#type' => 'password',
+      '#title' => $this->t('Password'),
+      '#description' => 'Password, #type = password',
+    ];
+
+    // Password Confirm
+    $form['password_confirm'] = [
+      '#type' => 'password_confirm',
+      '#title' => $this->t('New Password'),
+      '#description' => $this->t('PasswordConfirm, #type = password_confirm')
+    ];
+
+    // Range
+    $form['size'] = [
+      '#type' => 'range',
+      '#title' => t('Size'),
+      '#min' => 10,
+      '#max' => 100,
+      '#description' => $this->t('Range, #type = range'),
+    ];
+
+    // Radios
+    $form['settings']['active'] = [
+      '#type' => 'radios',
+      '#title' => t('Poll status'),
+      '#options' => [0 => $this->t('Closed'), 1 => $this->t('Active')],
+      '#description' => $this->t('Radios, #type = radios'),
+    ];
+
+    // Search
+    $form['search'] = [
+      '#type' => 'search',
+      '#title' => $this->t('Search'),
+      '#description' => $this->t('Search, #type = search'),
+    ];
+
+    // Select
+    $form['favorite'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Favorite color'),
+      '#options' => [
+        'red' => $this->t('Red'),
+        'blue' => $this->t('Blue'),
+        'green' => $this->t('Green')
+      ],
+      '#empty_option' => $this->t('-select-'),
+      '#description' => $this->t('Select, #type = select'),
+    ];
+
+    // Tel
+    $form['phone'] = [
+      '#type' => 'tel',
+      '#title' => $this->t('Phone'),
+      '#description' => $this->t('Tel, #type = tel'),
+    ];
+
+    // TableSelect
+    $options = [
+      1 => ['first_name' => 'Indy', 'last_name' => 'Jones'],
+      2 => ['first_name' => 'Darth', 'last_name' => 'Vader'],
+      3 => [ 'first_name' => 'Super', 'last_name' => 'Man'],
+    ];
+
+    $header = [
+      'first_name' => t('First Name'),
+      'last_name' => t('Last Name'),
+    ];
+
+    $form['table'] = [
+      '#type' => 'tableselect',
+      '#title' => $this->t('Users'),
+      '#header' => $header,
+      '#options' => $options,
+      '#empty' => t('No users found'),
+    ];
+
+    // Textarea
+    $form['text'] = [
+      '#type' => 'textarea',
+      '#title' => $this->t('Text'),
+      '#description' => $this->t('Textarea, #type = textarea')
+    ];
+
+    // Textfield
+    $form['subject'] = [
+      '#type' => 'textfield',
+      '#title' => t('Subject'),
+      '#size' => 60,
+      '#maxlength' => 128,
+      '#description' => $this->t('Textfield, #type = textfield'),
+    ];
+
+    // Weight
+    $form['weight'] = [
+      '#type' => 'weight',
+      '#title' => t('Weight'),
+      '#delta' => 10,
+      '#description' => $this->t('Weight, #type = weight')
+    ];
+
+
+    // Group submit handlers in an actions element with a key of "actions" so
+    // that it gets styled correctly, and so that other modules may add actions
+    // to the form.
+    $form['actions'] = [
+      '#type' => 'actions',
+    ];
+
+    // Extra actions for the display
+    $form['actions']['extra_actions'] = [
+      '#type' => 'dropbutton',
+      '#links' => [
+        'simple_form' => [
+          'title' => $this->t('Simple Form'),
+          'url' => Url::fromRoute('fapi_example.simple_form'),
+        ],
+        'demo' => [
+          'title' => $this->t('Build Demo'),
+          'url' => Url::fromRoute('fapi_example.build_demo'),
+        ],
+      ],
+    ];
+
+    // Add a submit button that handles the submission of the form.
+    $form['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Submit'),
+      '#description' => $this->t('Submit, #type = submit')
+    ];
+
+
+    return $form;
+  }
+
+  /**
+   * The form ID as used in alter hooks.
+   */
+  public function getFormId() {
+    return 'fapi_example_input_demo_form';
+  }
+
+  /**
+   * @param array $form
+   *   The built version of the render array representing the form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    //Find out what was submitted
+    $values = $form_state->getValues();
+    foreach($values  as $key => $value) {
+      $label = isset($form[$key]['#title']) ? $form[$key]['#title'] : $key;
+
+      // many arrays return 0 for unselected values so lets filter that out.
+      if (is_array($value)) $value = array_filter($value);
+
+      // Only display for controls that have titles and values.
+      if ($value && $label ) {
+        $display_value = is_array($value) ? preg_replace('/[\n\r\s]+/', ' ', print_r($value, 1)) : $value;
+        $message = $this->t('Value for %title: %value' , array('%title' => $label, '%value' => $display_value));
+        drupal_set_message($message);
+      }
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/fapi_example/src/Form/ModalForm.php b/fapi_example/src/Form/ModalForm.php
new file mode 100644
index 0000000..4e84959
--- /dev/null
+++ b/fapi_example/src/Form/ModalForm.php
@@ -0,0 +1,129 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Form\ModalForm.
+ */
+
+namespace Drupal\fapi_example\Form;
+
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\CloseModalDialogCommand;
+use Drupal\Core\Ajax\HtmlCommand;
+
+/**
+ * Implements the SimpleForm form controller.
+ *
+ * This class extends FormBase which is the simplest form base class used in
+ * Drupal.
+ *
+ * @see \Drupal\Core\Form\FormBase
+ * @see \Drupal\Core\Form\ConfigFormBase
+ */
+class ModalForm extends FormBase {
+
+  /**
+   * Build the simple form.
+   *
+   * A build form method constructs an array that defines how markup and
+   * other form elements are included in an HTML form.
+   *
+   * @param array $form
+   *   Default form array structure.
+   * @param FormStateInterface $form_state
+   *   Object containing current form state.
+   *
+   * @return array
+   *   The render array defining the elements of the form.
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['#prefix'] = '<div id="fapi-example-modal-form">';
+    $form['#suffix'] = '</div>';
+    $form['title'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Title'),
+      '#required' => TRUE,
+    ];
+
+    // Group submit handlers in an actions element with a key of "actions" so
+    // that it gets styled correctly, and so that other modules may add actions
+    // to the form.
+    $form['actions'] = [
+      '#type' => 'actions',
+    ];
+
+    // Add a submit button that handles the submission of the form.
+    $form['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Submit'),
+      '#ajax' => [
+        'callback' => '::ajaxSubmitForm',
+        'event' => 'click',
+      ]
+    ];
+
+    return $form;
+  }
+
+  /**
+   * Getter method for Form ID.
+   *
+   * The form ID is used in implementations of hook_form_alter() to allow other
+   * modules to alter the render array built by this form controller.  it must
+   * be unique site wide. It normally starts with the providing module's name.
+   *
+   * @return string
+   *   The unique ID of the form defined by this class.
+   */
+  public function getFormId() {
+    return 'fapi_example_modal_form';
+  }
+
+  /**
+   * Implements the submit handler  case.
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $title = $form_state->getValue('title');
+    $message = t('Submit handler: You specified a title of %title.', ['%title' => $title]);
+    drupal_set_message($message);
+  }
+
+  /**
+   * Implements the sumbit handler for the ajax call.
+   */
+  public function ajaxSubmitForm(array &$form, FormStateInterface $form_state) {
+
+    // At this point the submit handler has fired.
+    // Clear the message set by the submit handler.
+    drupal_get_messages();
+
+    // We begin building a new ajax reponse.
+    $response = new AjaxResponse();
+    if ($form_state->getErrors()) {
+      unset($form['#prefix']);
+      unset($form['#suffix']);
+      $form['status_messages'] = [
+        '#type' => 'status_messages',
+        '#weight' => -10,
+      ];
+      $response->addCommand(new HtmlCommand('#fapi-example-modal-form', $form));
+    }
+    else {
+      $title = $form_state->getValue('title');
+      $message = t('You specified a title of %title.', ['%title' => $title]);
+      $content = [
+        '#type' => 'html_tag',
+        '#tag' => 'p',
+        '#value' => $message,
+      ];
+      $response->addCommand(new HtmlCommand('#fapi-example-message', $content));
+      $response->addCommand(new CloseModalDialogCommand());
+    }
+    return $response;
+  }
+
+
+}
diff --git a/fapi_example/src/Form/SimpleForm.php b/fapi_example/src/Form/SimpleForm.php
new file mode 100644
index 0000000..25d4169
--- /dev/null
+++ b/fapi_example/src/Form/SimpleForm.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Form\SimpleForm.
+ */
+
+namespace Drupal\fapi_example\Form;
+
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Implements the SimpleForm form controller.
+ *
+ * This class extends FormBase which is the simplest form base class used in
+ * Drupal.
+ *
+ * @see \Drupal\Core\Form\FormBase
+ * @see \Drupal\Core\Form\ConfigFormBase
+ */
+class SimpleForm extends FormBase {
+
+  /**
+   * Build the simple form.
+   *
+   * A build form method constructs an array that defines how markup and
+   * other form elements are included in an HTML form.
+   *
+   * @param array $form
+   *   Default form array structure.
+   * @param FormStateInterface $form_state
+   *   Object containing current form state.
+   *
+   * @return array
+   *   The render array defining the elements of the form.
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+
+    $form['title'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Title'),
+      '#description' => $this->t('Title must be at least 5 characters in length.'),
+      '#required' => TRUE,
+    ];
+
+    // Group submit handlers in an actions element with a key of "actions" so
+    // that it gets styled correctly, and so that other modules may add actions
+    // to the form. This is not required, but is convention.
+    $form['actions'] = [
+      '#type' => 'actions',
+    ];
+
+    // Add a submit button that handles the submission of the form.
+    $form['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Submit'),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * Getter method for Form ID.
+   *
+   * The form ID is used in implementations of hook_form_alter() to allow other
+   * modules to alter the render array built by this form controller.  it must
+   * be unique site wide. It normally starts with the providing module's name.
+   *
+   * @return string
+   *   The unique ID of the form defined by this class.
+   */
+  public function getFormId() {
+    return 'fapi_example_simple_form';
+  }
+
+  /**
+   * Implements form validation.
+   *
+   * The validateForm method is the default method called to validate input on
+   * a form.
+   *
+   * @param array $form
+   *   The render array of the currently built form.
+   * @param FormStateInterface $form_state
+   *   Object describing the current state of the form.
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    $title = $form_state->getValue('title');
+    if (strlen($title) < 5) {
+      // Set an error for the form element with a key of "title".
+      $form_state->setErrorByName('title', $this->t('The title must be at least 5 characters long.'));
+    }
+  }
+
+  /**
+   * Implements a form submit handler.
+   *
+   * The submitForm method is the default method called for any submit elements.
+   *
+   * @param array $form
+   *   The render array of the currently built form.
+   * @param FormStateInterface $form_state
+   *   Object describing the current state of the form.
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    /*
+     * This would normally be replaced by code that actually does something
+     * with the title.
+     */
+    $title = $form_state->getValue('title');
+    drupal_set_message(t('You specified a title of %title.', ['%title' => $title]));
+  }
+
+}
diff --git a/fapi_example/src/Form/StateDemo.php b/fapi_example/src/Form/StateDemo.php
new file mode 100644
index 0000000..104bf28
--- /dev/null
+++ b/fapi_example/src/Form/StateDemo.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Form\StateDemo.
+ */
+
+namespace Drupal\fapi_example\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+
+
+/**
+ * Implements the state demo form controller.
+ *
+ * The submit handler for this form is implemented by the DemoBase class.
+ *
+ * @see \Drupal\Core\Form\FormBase
+ * @see \Drupal\Core\Form\ConfigFormBase
+ */
+class StateDemo extends DemoBase {
+
+  /**
+   * Build the simple form.
+   *
+   * @inheritdoc
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['needs_accommodation'] = [
+      '#type' => 'checkbox',
+      '#title' => 'Need Special Accommodations?',
+    ];
+
+    // The #states property used here binds the visibility of the of the
+    // container element to the value of the needs_accommodation checkbox above.
+    $form['accommodation'] = [
+     '#type' => 'container',
+     '#attributes' => [
+       'class' => 'accommodation',
+     ],
+     '#states' => [
+       'invisible' => [
+         'input[name="needs_accommodation"]' => ['checked' => FALSE],
+       ],
+     ],
+   ];
+
+   $form['accommodation']['diet'] = [
+     '#type' => 'textfield',
+     '#title' => t('Dietary Restrictions'),
+   ];
+
+    // Add a submit button that handles the submission of the form.
+    $form['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Submit'),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * Getter method for Form ID.
+   *
+   * @inheritdoc
+   */
+  public function getFormId() {
+    return 'fapi_example_state_demo';
+  }
+
+  /**
+   * Implements submitForm callback.
+   *
+   * @inheritdoc
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    //Find out what was submitted
+    $values = $form_state->getValues();
+    if ($values['needs_accommodation']) {
+      drupal_set_message($this->t('Dietary Restriction Requested: %diet', ['%diet' => $values['diet']]));
+    }
+  }
+
+
+}
diff --git a/fapi_example/src/Form/VerticalTabsDemo.php b/fapi_example/src/Form/VerticalTabsDemo.php
new file mode 100644
index 0000000..cfc2130
--- /dev/null
+++ b/fapi_example/src/Form/VerticalTabsDemo.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Form\VerticalTabsDemo.
+ */
+
+namespace Drupal\fapi_example\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+
+
+/**
+ * Implements the vertical tabs demo form controller.
+ *
+ * This class extends FormBase which is the simplest form base class used in
+ * Drupal.
+ *
+ * @see \Drupal\Core\Form\FormBase
+ * @see \Drupal\Core\Form\ConfigFormBase
+ */
+class VerticalTabsDemo extends DemoBase {
+
+  /**
+   * Build the form.
+   *
+   * @inheritdoc
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+
+    $form['information'] = [
+      '#type' => 'vertical_tabs',
+      '#default_tab' => 'edit-publication',
+    ];
+
+    $form['author'] = [
+     '#type' => 'details',
+     '#title' => 'Author',
+     '#group' => 'information',
+    ];
+
+    $form['author']['name'] = [
+     '#type' => 'textfield',
+     '#title' => t('Name'),
+    ];
+
+    $form['publication'] = [
+     '#type' => 'details',
+     '#title' => t('Publication'),
+     '#group' => 'information',
+    ];
+
+    $form['publication']['publisher'] = [
+     '#type' => 'textfield',
+     '#title' => t('Publisher'),
+    ];
+
+    $form['actions'] = ['#type' => 'actions'];
+    // Add a submit button that handles the submission of the form.
+    $form['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Submit'),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * Getter method for Form ID.
+   *
+   * @inheritdoc
+   */
+  public function getFormId() {
+    return 'fapi_example_vertical_tabs_demo';
+  }
+
+}
diff --git a/fapi_example/src/Tests/AjaxDemoTest.php b/fapi_example/src/Tests/AjaxDemoTest.php
new file mode 100644
index 0000000..865fff4
--- /dev/null
+++ b/fapi_example/src/Tests/AjaxDemoTest.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Test for the State Demo form example.
+ */
+
+namespace Drupal\fapi_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Ensure that the fapi_example forms work properly.
+ *
+ * @see Drupal\simpletest\WebTestBase
+ *
+ * SimpleTest uses group annotations to help you organize your tests.
+ *
+ * @group fapi_example
+ *
+ * @ingroup fapi_example
+ */
+class AjaxDemoTest extends WebTestBase {
+
+  /**
+   * Our module dependencies.
+   *
+   * @var array List of test dependencies.
+   */
+  static public $modules = array('fapi_example');
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string Installation profile required for test.
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test example forms provided by fapi_example.
+   */
+  public function testAjaxDemoForm() {
+
+    // Test for a link to the simple_form example on the form_example page.
+    $this->drupalGet('examples/fapi_example');
+    $this->assertLinkByHref('examples/fapi_example/ajax_demo');
+
+    // Verify that anonymous can access the page.
+    $this->drupalGet('examples/fapi_example/ajax_demo');
+    $this->assertResponse(200, 'The Demo of Ajax page is available.');
+
+    // Post the form.
+    $edit = [
+      'temperature' => 'warm',
+    ];
+    $this->drupalPostForm('/examples/fapi_example/ajax_demo', $edit, t('Submit'));
+    $this->assertText('Value for Temperature: warm');
+  }
+}
diff --git a/fapi_example/src/Tests/BuildDemoTest.php b/fapi_example/src/Tests/BuildDemoTest.php
new file mode 100644
index 0000000..bf3ece6
--- /dev/null
+++ b/fapi_example/src/Tests/BuildDemoTest.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\fapi_example\Tests\BuildDemoTest
+ */
+
+namespace Drupal\fapi_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Ensure that the fapi_example forms work properly.
+ *
+ * @see Drupal\simpletest\WebTestBase
+ *
+ * SimpleTest uses group annotations to help you organize your tests.
+ *
+ * @group fapi_example
+ *
+ * @ingroup fapi_example
+ */
+class BuildDemoTest extends WebTestBase {
+
+  /**
+   * Our module dependencies.
+   *
+   * @var array List of test dependencies.
+   */
+  static public $modules = array('fapi_example');
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string Installation profile required for test.
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test example forms provided by fapi_example.
+   */
+  public function testBuildDemo() {
+
+    // Test for a link to the simple_form example on the form_example page.
+    $this->drupalGet('examples/fapi_example');
+    $this->assertLinkByHref('examples/fapi_example/build_demo');
+
+    // Verify that anonymous can access the page.
+    $this->drupalGet('examples/fapi_example/build_demo');
+    $this->assertResponse(200, 'The Build Demoq Form is available.');
+
+    // Post the form.
+    $edit = [
+      'change' => '1',
+    ];
+    $this->drupalPostForm('/examples/fapi_example/build_demo', $edit, t('Submit'));
+    $this->assertText('1. __construct');
+    $this->assertText('2. getFormId');
+    $this->assertText('3. validateForm');
+    $this->assertText('4. submitForm');
+  }
+
+}
diff --git a/fapi_example/src/Tests/ContainerDemoTest.php b/fapi_example/src/Tests/ContainerDemoTest.php
new file mode 100644
index 0000000..25cc9c3
--- /dev/null
+++ b/fapi_example/src/Tests/ContainerDemoTest.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Test for the State Demo form example.
+ */
+
+namespace Drupal\fapi_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Ensure that the fapi_example forms work properly.
+ *
+ * @see Drupal\simpletest\WebTestBase
+ *
+ * SimpleTest uses group annotations to help you organize your tests.
+ *
+ * @group fapi_example
+ *
+ * @ingroup fapi_example
+ */
+class ContainerDemoTest extends WebTestBase {
+
+  /**
+   * Our module dependencies.
+   *
+   * @var array List of test dependencies.
+   */
+  static public $modules = array('fapi_example');
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string Installation profile required for test.
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test example forms provided by fapi_example.
+   */
+  public function testContainerDemoForm() {
+
+    // Test for a link to the simple_form example on the form_example page.
+    $this->drupalGet('examples/fapi_example');
+    $this->assertLinkByHref('examples/fapi_example/container_demo');
+
+    // Verify that anonymous can access the simpletest_examples page.
+    $this->drupalGet('examples/fapi_example/container_demo');
+    $this->assertResponse(200, 'The Demo of Container page is available.');
+
+    // Post the form.
+    $edit = [
+      'name' => 'Dave',
+      'pen_name' => 'DMan',
+      'title' => 'My Book',
+      'publisher' => 'me',
+      'diet' => 'vegan'
+    ];
+    $this->drupalPostForm('/examples/fapi_example/container_demo', $edit, t('Submit'));
+    $this->assertText('Value for name: Dave');
+    $this->assertText('Value for pen_name: DMan');
+    $this->assertText('Value for title: My Book');
+    $this->assertText('Value for publisher: me');
+    $this->assertText('Value for diet: vegan');
+  }
+}
diff --git a/fapi_example/src/Tests/InputDemoTest.php b/fapi_example/src/Tests/InputDemoTest.php
new file mode 100644
index 0000000..2beb633
--- /dev/null
+++ b/fapi_example/src/Tests/InputDemoTest.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Test for the Input Demo form.
+ */
+
+namespace Drupal\fapi_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Ensure that the fapi_example forms work properly.
+ *
+ * @see Drupal\simpletest\WebTestBase
+ *
+ * SimpleTest uses group annotations to help you organize your tests.
+ *
+ * @group fapi_example
+ *
+ * @ingroup fapi_example
+ */
+class InputDemoTest extends WebTestBase {
+
+  /**
+   * Our module dependencies.
+   *
+   * @var array List of test dependencies.
+   */
+  static public $modules = array('fapi_example');
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string Installation profile required for test.
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test example forms provided by fapi_example.
+   */
+  public function testInputDemoForm() {
+    // Test for a link to the form_example in the Tools menu.
+    $this->drupalGet('');
+    $this->assertResponse(200, 'The Home page is available.');
+    $this->assertLinkByHref('examples/fapi_example');
+
+    // Test for a link to the simple_form example on the form_example page.
+    $this->drupalGet('examples/fapi_example');
+    $this->assertLinkByHref('examples/fapi_example/input_demo');
+
+    // Verify that anonymous can access the simpletest_examples page.
+    $this->drupalGet('examples/fapi_example/input_demo');
+    $this->assertResponse(200, 'The Demo of Common Input Elements page is available.');
+
+    // Post the form.
+    $edit = [
+      'tests_taken[SAT]' => TRUE,
+      'color' => '#ff6bf1',
+      'expiration' => '2015-10-21',
+      'email' => 'somebody@example.org',
+      'quantity' => '4',
+      'password' => 'letmein',
+      'password_confirm[pass1]' => 'letmein',
+      'password_confirm[pass2]' => 'letmein',
+      'size' => '76',
+      'active' => '1',
+      'search' => 'my search string',
+      'favorite' => 'blue',
+      'phone' => '555-555-5555',
+      'table[1]' => TRUE,
+      'table[3]' => TRUE,
+      'text' => 'This is a test of my form.',
+      'subject' => 'Form test',
+      'weight' => '3',
+    ];
+    $this->drupalPostForm('/examples/fapi_example/input_demo', $edit, t('Submit'));
+    $this->assertText('Value for What standardized tests did you take?: Array ( [SAT] =&gt; SAT )');
+    $this->assertText('Value for Color: #ff6bf1');
+    $this->assertText('Value for Content expiration: 2015-10-21');
+    $this->assertText('Value for Email: somebody@example.org');
+    $this->assertText('Value for Quantity: 4');
+    $this->assertText('Value for Password: letmein');
+    $this->assertText('Value for New Password: letmein');
+    $this->assertText('Value for Size: 76');
+    $this->assertText('Value for active: 1');
+    $this->assertText('Value for Search: my search string');
+    $this->assertText('Value for Favorite color: blue');
+    $this->assertText('Value for Phone: 555-555-5555');
+    $this->assertText('Value for Users: Array ( [1] =&gt; 1 [3] =&gt; 3 )');
+    $this->assertText('Value for Text: This is a test of my form.');
+    $this->assertText('Value for Subject: Form test');
+    $this->assertText('Value for Weight: 3');
+  }
+}
\ No newline at end of file
diff --git a/fapi_example/src/Tests/ModalFormTest.php b/fapi_example/src/Tests/ModalFormTest.php
new file mode 100644
index 0000000..d8f484d
--- /dev/null
+++ b/fapi_example/src/Tests/ModalFormTest.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Test for the State Demo form example.
+ */
+
+namespace Drupal\fapi_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Ensure that the fapi_example forms work properly.
+ *
+ * @see Drupal\simpletest\WebTestBase
+ *
+ * SimpleTest uses group annotations to help you organize your tests.
+ *
+ * @group fapi_example
+ *
+ * @ingroup fapi_example
+ */
+class ModalFormTest extends WebTestBase {
+
+  /**
+   * Our module dependencies.
+   *
+   * @var array List of test dependencies.
+   */
+  static public $modules = array('fapi_example');
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string Installation profile required for test.
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test example forms provided by fapi_example.
+   */
+  public function testModalForm() {
+
+    // Test for a link to the simple_form example on the form_example page.
+    $this->drupalGet('examples/fapi_example');
+    $this->assertLinkByHref('examples/fapi_example/modal_form');
+
+    // Verify that anonymous can access the page.
+    $this->drupalGet('examples/fapi_example/modal_form');
+    $this->assertResponse(200, 'The Demo of Modal Form is available.');
+
+    // Post the form.
+    $edit = [
+      'title' => 'My Book',
+    ];
+    $this->drupalPostForm('/examples/fapi_example/modal_form', $edit, t('Submit'));
+    $this->assertText('Submit handler: You specified a title of My Book.');
+  }
+
+}
diff --git a/fapi_example/src/Tests/SimpleFormTest.php b/fapi_example/src/Tests/SimpleFormTest.php
new file mode 100644
index 0000000..aaced9f
--- /dev/null
+++ b/fapi_example/src/Tests/SimpleFormTest.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Test for the Simple Form example.
+ */
+
+namespace Drupal\fapi_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Ensure that the fapi_example forms work properly.
+ *
+ * @see Drupal\simpletest\WebTestBase
+ *
+ * SimpleTest uses group annotations to help you organize your tests.
+ *
+ * @group fapi_example
+ *
+ * @ingroup fapi_example
+ */
+class SimpleFormTest extends WebTestBase {
+
+  /**
+   * Our module dependencies.
+   *
+   * @var array List of test dependencies.
+   */
+  static public $modules = array('fapi_example');
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string Installation profile required for test.
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test example forms provided by fapi_example.
+   *
+   * Check if SimpleTest Example can successfully return its main page,
+   * if there is a link to the simpletest_example in the Tools menu.
+   */
+  public function testSimpleFormExample() {
+    // Test for a link to the form_example in the Tools menu.
+    $this->drupalGet('');
+    $this->assertResponse(200, 'The Home page is available.');
+    $this->assertLinkByHref('examples/fapi_example');
+
+    // Test for a link to the simple_form example on the form_example page.
+    $this->drupalGet('examples/fapi_example');
+    $this->assertLinkByHref('examples/fapi_example/simple_form');
+
+    // Verify that anonymous can access the simpletest_examples page.
+    $this->drupalGet('examples/fapi_example/simple_form');
+    $this->assertResponse(200, 'The Simple Form Example page is available.');
+
+    // Post a title.
+    $edit = ['title' => 'My Custom Title'];
+    $this->drupalPostForm('/examples/fapi_example/simple_form', $edit, t('Submit'));
+    $this->assertText('You specified a title of My Custom Title.');
+  }
+
+}
diff --git a/fapi_example/src/Tests/StateDemoTest.php b/fapi_example/src/Tests/StateDemoTest.php
new file mode 100644
index 0000000..aa3a7a8
--- /dev/null
+++ b/fapi_example/src/Tests/StateDemoTest.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @file
+ * Test for the State Demo form example.
+ */
+
+namespace Drupal\fapi_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Ensure that the fapi_example forms work properly.
+ *
+ * @see Drupal\simpletest\WebTestBase
+ *
+ * SimpleTest uses group annotations to help you organize your tests.
+ *
+ * @group fapi_example
+ *
+ * @ingroup fapi_example
+ */
+class StateDemoTest extends WebTestBase {
+
+  /**
+   * Our module dependencies.
+   *
+   * @var array List of test dependencies.
+   */
+  static public $modules = array('fapi_example');
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string Installation profile required for test.
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test example forms provided by fapi_example.
+   */
+  public function testStateDemoForm() {
+    // Test for a link to the form_example in the Tools menu.
+    $this->drupalGet('');
+    $this->assertResponse(200, 'The Home page is available.');
+    $this->assertLinkByHref('examples/fapi_example');
+
+    // Test for a link to the simple_form example on the form_example page.
+    $this->drupalGet('examples/fapi_example');
+    $this->assertLinkByHref('examples/fapi_example/state_demo');
+
+    // Verify that anonymous can access the simpletest_examples page.
+    $this->drupalGet('examples/fapi_example/state_demo');
+    $this->assertResponse(200, 'The Demo of Form State Binding page is available.');
+
+    // Post the form.
+    $edit = [
+      'needs_accommodation' => TRUE,
+      'diet' => 'vegan',
+    ];
+    $this->drupalPostForm('/examples/fapi_example/state_demo', $edit, t('Submit'));
+    $this->assertText('Dietary Restriction Requested: vegan');
+  }
+}
diff --git a/fapi_example/src/Tests/VerticalTabsDemoTest.php b/fapi_example/src/Tests/VerticalTabsDemoTest.php
new file mode 100644
index 0000000..6405cb1
--- /dev/null
+++ b/fapi_example/src/Tests/VerticalTabsDemoTest.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * Test for the State Demo form example.
+ */
+
+namespace Drupal\fapi_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Ensure that the fapi_example forms work properly.
+ *
+ * @see Drupal\simpletest\WebTestBase
+ *
+ * SimpleTest uses group annotations to help you organize your tests.
+ *
+ * @group fapi_example
+ *
+ * @ingroup fapi_example
+ */
+class VerticalTabsDemoTest extends WebTestBase {
+
+  /**
+   * Our module dependencies.
+   *
+   * @var array List of test dependencies.
+   */
+  static public $modules = array('fapi_example');
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string Installation profile required for test.
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test example forms provided by fapi_example.
+   */
+  public function testVerticalTabsDemoForm() {
+
+    // Test for a link to the simple_form example on the form_example page.
+    $this->drupalGet('examples/fapi_example');
+    $this->assertLinkByHref('examples/fapi_example/vertical_tabs_demo');
+
+    // Verify that anonymous can access the simpletest_examples page.
+    $this->drupalGet('examples/fapi_example/vertical_tabs_demo');
+    $this->assertResponse(200, 'The Demo of Container page is available.');
+
+    // Post the form.
+    $edit = [
+      'name' => 'Dave',
+      'publisher' => 'me',
+    ];
+    $this->drupalPostForm('/examples/fapi_example/container_demo', $edit, t('Submit'));
+    $this->assertText('Value for name: Dave');
+    $this->assertText('Value for publisher: me');
+  }
+}
