diff --git a/config/schema/inline_entity_form.schema.yml b/config/schema/inline_entity_form.schema.yml
index 69c7e4b..5f2f6b6 100644
--- a/config/schema/inline_entity_form.schema.yml
+++ b/config/schema/inline_entity_form.schema.yml
@@ -1,6 +1,6 @@
 # Schema for the Inline Entity Reference module display settings.
 
-field.widget.settings.inline_entity_form_single:
+field.widget.settings.inline_entity_form_simple:
   type: mapping
   label: 'Inline entity reference display format settings'
   mapping:
@@ -13,6 +13,15 @@ field.widget.settings.inline_entity_form_single:
     label_plural:
       type: string
       label: "Label (plural)"
+    allow_new:
+      type: boolean
+      label: "Allow new"
+    allow_existing:
+      type: boolean
+      label: "Allow existing"
+    match_operator:
+      type: string
+      label: "Match operator"
 
 field.widget.settings.inline_entity_form_multiple:
   type: mapping
diff --git a/src/Element/InlineEntityForm.php b/src/Element/InlineEntityForm.php
index 48367a6..8cfe5f2 100644
--- a/src/Element/InlineEntityForm.php
+++ b/src/Element/InlineEntityForm.php
@@ -144,14 +144,24 @@ class InlineEntityForm extends RenderElement {
     $submit = array_merge([[get_called_class(), 'triggerIefSubmit']], $complete_form['#submit']);
 
     if (!empty($complete_form['submit'])) {
-      $complete_form['submit']['#submit'] = empty($complete_form['submit']['#submit']) ? $submit : array_merge($submit, $complete_form['submit']['#submit']);
+      if (empty($complete_form['submit']['#submit'])) {
+        $complete_form['submit']['#submit'] = $submit;
+      }
+      else {
+        $complete_form['submit']['#submit'] = array_merge([[get_called_class(), 'triggerIefSubmit']], $complete_form['submit']['#submit']);
+      }
       $complete_form['submit']['#ief_submit_all'] = TRUE;
       $submit_attached = TRUE;
     }
 
     foreach (['submit', 'publish', 'unpublish'] as $action) {
       if (!empty($complete_form['actions'][$action])) {
-        $complete_form['actions'][$action]['#submit'] = empty($complete_form['actions'][$action]['#submit']) ? $submit : array_merge($submit, $complete_form['actions'][$action]['#submit']);
+        if (empty($complete_form['actions'][$action]['#submit'])) {
+          $complete_form['actions'][$action]['#submit'] = $submit;
+        }
+        else {
+          $complete_form['actions'][$action]['#submit'] = array_merge([[get_called_class(), 'triggerIefSubmit']], $complete_form['actions'][$action]['#submit']);
+        }
         $complete_form['actions'][$action]['#ief_submit_all'] = TRUE;
         $submit_attached = TRUE;
       }
diff --git a/src/InlineEntityForm/EntityInlineEntityFormHandler.php b/src/InlineEntityForm/EntityInlineEntityFormHandler.php
index 2159dc9..386c104 100644
--- a/src/InlineEntityForm/EntityInlineEntityFormHandler.php
+++ b/src/InlineEntityForm/EntityInlineEntityFormHandler.php
@@ -188,7 +188,12 @@ class EntityInlineEntityFormHandler implements InlineEntityFormHandlerInterface
       $controller = \Drupal::entityManager()
         ->getFormObject($entity->getEntityTypeId(), $operation);
       $child_form_state = static::buildChildFormState($controller, $form_state, $entity, $operation);
-      $controller->validateForm($entity_form, $child_form_state);
+      $entity_form['#entity'] = $controller->validateForm($entity_form, $child_form_state);
+
+      // TODO - this is field-only part of the code. Figure out how to refactor.
+      if ($child_form_state->has(['inline_entity_form', $entity_form['#ief_id']])) {
+        $form_state->set(['inline_entity_form', $entity_form['#ief_id'], 'entity'], $entity_form['#entity']);
+      }
 
       foreach($child_form_state->getErrors() as $name => $message) {
         $form_state->setErrorByName($name, $message);
@@ -230,7 +235,7 @@ class EntityInlineEntityFormHandler implements InlineEntityFormHandlerInterface
       // exception from being thrown.
       $controller->getEntity()->setValidationRequired(FALSE);
     }
-    $controller->save($child_form, $child_form_state);
+
     $entity_form['#entity'] = $controller->getEntity();
 
     if ($entity_form['#save_entity']) {
@@ -238,11 +243,8 @@ class EntityInlineEntityFormHandler implements InlineEntityFormHandlerInterface
     }
 
     // TODO - this is field-only part of the code. Figure out how to refactor.
-    if ($child_form_state->get('inline_entity_form')) {
-      foreach ($child_form_state->get('inline_entity_form') as $id => $data) {
-        $data['entity'] = $entity_form['#entity'];
-        $form_state->set(['inline_entity_form', $id], $data);
-      }
+    if ($child_form_state->has(['inline_entity_form', $entity_form['#ief_id']])) {
+      $form_state->set(['inline_entity_form', $entity_form['#ief_id'], 'entity'], $entity_form['#entity']);
     }
 
   }
diff --git a/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php b/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php
index 2aa0dc0..9737514 100644
--- a/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php
+++ b/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php
@@ -7,11 +7,13 @@
 
 namespace Drupal\inline_entity_form\Plugin\Field\FieldWidget;
 
+use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\WidgetBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Render\Element;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -228,4 +230,169 @@ abstract class InlineEntityFormBase extends WidgetBase implements ContainerFacto
     }
   }
 
+  /**
+   * Checks whether we can build entity form at all.
+   *
+   * - Is IEF handler loaded?
+   * - Are we on a "real" entity form and not on default value widget?
+   *
+   * @param FormStateInterface $form_state
+   *   Form state.
+   *
+   * @return bool
+   *   TRUE if we are able to proceed with form build and FALSE if not.
+   */
+  protected function canBuildForm(FormStateInterface $form_state) {
+    if ($this->isDefaultValueWidget($form_state)) {
+      return FALSE;
+    }
+
+    if (!$this->iefHandler) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+
+  /**
+   * Gets inline entity form element.
+   *
+   * @param $operation
+   *   Operation (i.e. 'add' or 'edit').
+   * @param $target_type
+   *   Target entity type.
+   * @param $language
+   *   Entity langcode.
+   * @param array $parents
+   *   Array of parent element names.
+   * @param EntityInterface $entity
+   *   Optional entity object.
+   * @param bool $save_entity
+   *   IEF will attempt to save entity after attaching all field values if set to
+   *   TRUE. Defaults to FALSE.
+   *
+   * @return array
+   *   IEF form element structure.
+   */
+  protected function getInlineEntityForm($operation, $target_type, $language, $delta, array $parents, $bundle = NULL, EntityInterface $entity = NULL, $save_entity = FALSE) {
+    $ief = [
+      '#type' => 'inline_entity_form',
+      '#op' => $operation,
+      '#save_entity' => $save_entity,
+      '#ief_row_delta' => $delta,
+      // Used by Field API and controller methods to find the relevant
+      // values in $form_state.
+      '#parents' => $parents,
+      '#entity_type' => $target_type,
+      // Pass the langcode of the parent entity,
+      '#language' => $language,
+      // Labels could be overridden in field widget settings. We won't have
+      // access to those in static callbacks (#process, ...) so let's add
+      // them here.
+      '#ief_labels' => $this->labels(),
+      // Identifies the IEF widget to which the form belongs.
+      '#ief_id' => $this->getIefId(),
+      // Add the pre_render callback that powers the #fieldset form element key,
+      // which moves the element to the specified fieldset without modifying its
+      // position in $form_state->get('values').
+      '#pre_render' => [[get_class($this), 'addFieldsetMarkup']],
+    ];
+
+    if ($entity) {
+      // Store the entity on the form, later modified in the controller.
+      $ief['#entity'] = $entity;
+    }
+
+    if ($bundle) {
+      $ief['#bundle'] = $bundle;
+    }
+
+    return $ief;
+  }
+
+  /**
+   * Adds submit callbacks to the inline entity form.
+   *
+   * @param array $element
+   *   Form array structure.
+   */
+  public static function addIefSubmitCallbacks($element) {
+    $element['#ief_element_submit'][] = [get_called_class(), 'submitSaveEntity'];
+    return $element;
+  }
+
+  /**
+   * Pre-render callback: Move form elements into fieldsets for presentation purposes.
+   *
+   * Inline forms use #tree = TRUE to keep their values in a hierarchy for
+   * easier storage. Moving the form elements into fieldsets during form building
+   * would break up that hierarchy, so it's not an option for Field API fields.
+   * Therefore, we wait until the pre_render stage, where any changes we make
+   * affect presentation only and aren't reflected in $form_state->getValues().
+   */
+  public static function addFieldsetMarkup($form) {
+    $sort = [];
+    foreach (Element::children($form) as $key) {
+      $element = $form[$key];
+      // In our form builder functions, we added an arbitrary #fieldset property
+      // to any element that belongs in a fieldset. If this form element has that
+      // property, move it into its fieldset.
+      if (isset($element['#fieldset']) && isset($form[$element['#fieldset']])) {
+        $form[$element['#fieldset']][$key] = $element;
+        // Remove the original element this duplicates.
+        unset($form[$key]);
+        // Mark the fieldset for sorting.
+        if (!in_array($key, $sort)) {
+          $sort[] = $element['#fieldset'];
+        }
+      }
+    }
+
+    // Sort all fieldsets, so that element #weight stays respected.
+    foreach ($sort as $key) {
+      uasort($form[$key], 'element_sort');
+    }
+
+    return $form;
+  }
+
+  /**
+   * Marks created/edited entity with "needs save" flag.
+   *
+   * Note that at this point the entity is not yet saved, since the user might
+   * still decide to cancel the parent form.
+   *
+   * @param $entity_form
+   *  The form of the entity being managed inline.
+   * @param $form_state
+   *   The form state of the parent form.
+   */
+  public static function submitSaveEntity($entity_form, FormStateInterface $form_state) {
+    $ief_id = $entity_form['#ief_id'];
+    $entity = $entity_form['#entity'];
+
+    if ($entity_form['#op'] == 'add') {
+      // Determine the correct weight of the new element.
+      $weight = 0;
+      $entities = $form_state->get(['inline_entity_form', $ief_id, 'entities']);
+      if (!empty($entities)) {
+        $weight = max(array_keys($entities)) + 1;
+      }
+      // Add the entity to form state, mark it for saving, and close the form.
+      $entities[] = array(
+        'entity' => $entity,
+        '_weight' => $weight,
+        'form' => NULL,
+        'needs_save' => TRUE,
+      );
+      $form_state->set(['inline_entity_form', $ief_id, 'entities'], $entities);
+    }
+    else {
+      $delta = $entity_form['#ief_row_delta'];
+      $entities = $form_state->get(['inline_entity_form', $ief_id, 'entities']);
+      $entities[$delta]['entity'] = $entity;
+      $entities[$delta]['needs_save'] = TRUE;
+      $form_state->set(['inline_entity_form', $ief_id, 'entities'], $entities);
+    }
+  }
 }
diff --git a/src/Plugin/Field/FieldWidget/InlineEntityFormMultiple.php b/src/Plugin/Field/FieldWidget/InlineEntityFormMultiple.php
index 9f2fa41..a5678c2 100644
--- a/src/Plugin/Field/FieldWidget/InlineEntityFormMultiple.php
+++ b/src/Plugin/Field/FieldWidget/InlineEntityFormMultiple.php
@@ -10,6 +10,7 @@ namespace Drupal\inline_entity_form\Plugin\Field\FieldWidget;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Component\Utility\SortArray;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\WidgetBase;
@@ -33,6 +34,51 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 class InlineEntityFormMultiple extends InlineEntityFormBase implements ContainerFactoryPluginInterface {
 
   /**
+   * Module handler service.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * Constructs a InlineEntityFormBase object.
+   *
+   * @param array $plugin_id
+   *   The plugin_id for the widget.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   The definition of the field to which the widget is associated.
+   * @param array $settings
+   *   The widget settings.
+   * @param array $third_party_settings
+   *   Any third party settings.
+   * @param \Drupal\Core\Entity\EntityManager $entity_manager
+   *   Entity manager service.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   Module handler service.
+   */
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings, $entity_manager);
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['third_party_settings'],
+      $container->get('entity.manager'),
+      $container->get('module_handler')
+    );
+  }
+
+  /**
    * {@inheritdoc}
    */
   public static function defaultSettings() {
@@ -125,14 +171,13 @@ class InlineEntityFormMultiple extends InlineEntityFormBase implements Container
    * {@inheritdoc}
    */
   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
-    if ($this->isDefaultValueWidget($form_state)) {
-      return $element;
-    }
-    if (!$this->iefHandler) {
+    if (!$this->canBuildForm($form_state)) {
       return $element;
     }
 
     $settings = $this->getFieldSettings();
+
+    // Get the entity type labels for the UI strings.
     $labels = $this->labels();
 
     // Build a parents array for this element's values in the form.
@@ -227,7 +272,7 @@ class InlineEntityFormMultiple extends InlineEntityFormBase implements Container
       'entity_type' => $settings['target_type'],
       'allowed_bundles' => $target_bundles,
     );
-    \Drupal::moduleHandler()->alter('inline_entity_form_table_fields', $fields, $context);
+    $this->moduleHandler->alter('inline_entity_form_table_fields', $fields, $context);
     $element['entities']['#table_fields'] = $fields;
 
     $weight_delta = max(ceil(count($entities) * 1.2), 50);
@@ -259,36 +304,21 @@ class InlineEntityFormMultiple extends InlineEntityFormBase implements Container
           $element['entities'][$key]['form'] = [
             '#type' => 'container',
             '#attributes' => ['class' => ['ief-form', 'ief-form-row']],
-            'inline_entity_form' => [
-              '#type' => 'inline_entity_form',
-              '#op' => $value['form'],
-              '#save_entity' => FALSE,
-              // Used by Field API and controller methods to find the relevant
-              // values in $form_state.
-              '#parents' => array_merge($parents, ['inline_entity_form', 'entities', $key, 'form']),
-              // Store the entity on the form, later modified in the controller.
-              '#entity' => $entity,
-              '#entity_type' => $settings['target_type'],
-              // Pass the langcode of the parent entity,
-              '#language' => $parent_langcode,
-              // Labels could be overridden in field widget settings. We won't have
-              // access to those in static callbacks (#process, ...) so let's add
-              // them here.
-              '#ief_labels' => $this->labels(),
-              // Identifies the IEF widget to which the form belongs.
-              '#ief_id' => $this->getIefId(),
-              // Identifies the table row to which the form belongs.
-              '#ief_row_delta' => $key,
-              // Add the pre_render callback that powers the #fieldset form element key,
-              // which moves the element to the specified fieldset without modifying its
-              // position in $form_state->get('values').
-              '#pre_render' => ['inline_entity_form_pre_render_add_fieldset_markup'],
-              '#process' => [
-                ['\Drupal\inline_entity_form\Element\InlineEntityForm', 'processEntityForm'],
-                [get_class($this), 'buildEntityFormActions'],
-                [get_class($this), 'addIefSubmitCallbacks'],
-              ]
-            ]
+            'inline_entity_form' => $this->getInlineEntityForm(
+              $value['form'],
+              $settings['target_type'],
+              $parent_langcode,
+              $key,
+              array_merge($parents,  ['inline_entity_form', 'entities', $key, 'form']),
+              $entity->bundle(),
+              $entity
+            ),
+          ];
+
+          $element['entities'][$key]['form']['inline_entity_form']['#process'] = [
+            ['\Drupal\inline_entity_form\Element\InlineEntityForm', 'processEntityForm'],
+            [get_class($this), 'addIefSubmitCallbacks'],
+            [get_class($this), 'buildEntityFormActions'],
           ];
         }
         elseif ($value['form'] == 'remove') {
@@ -474,35 +504,19 @@ class InlineEntityFormMultiple extends InlineEntityFormBase implements Container
         $element['form'] = [
           '#type' => 'fieldset',
           '#attributes' => ['class' => ['ief-form', 'ief-form-bottom']],
-          'inline_entity_form' => [
-            '#type' => 'inline_entity_form',
-            '#op' => 'add',
-            '#save_entity' => FALSE,
-            '#entity_type' => $settings['target_type'],
-            '#bundle' => $this->determineBundle($form_state),
-            '#language' => $parent_langcode,
-            // Labels could be overridden in field widget settings. We won't have
-            // access to those in static callbacks (#process, ...) so let's add
-            // them here.
-            '#ief_labels' => $this->labels(),
-            // Identifies the IEF widget to which the form belongs.
-            '#ief_id' => $this->getIefId(),
-            // Used by Field API and controller methods to find the relevant
-            // values in $form_state.
-            '#parents' => array_merge($parents, ['inline_entity_form']),
-            // Add the pre_render callback that powers the #fieldset form element key,
-            // which moves the element to the specified fieldset without modifying its
-            // position in $form_state->get('values').
-            '#pre_render' => ['inline_entity_form_pre_render_add_fieldset_markup'],
-            // We need to add our own #process callback that adds action elements,
-            // but still keep default callback which makes sure everything will
-            // actually work.
-            '#process' => [
-              ['\Drupal\inline_entity_form\Element\InlineEntityForm', 'processEntityForm'],
-              [get_class($this), 'buildEntityFormActions'],
-              [get_class($this), 'addIefSubmitCallbacks'],
-            ],
-          ],
+          'inline_entity_form' => $this->getInlineEntityForm(
+            'add',
+            $settings['target_type'],
+            $parent_langcode,
+            NULL,
+            array_merge($parents, ['inline_entity_form']),
+            $this->determineBundle($form_state)
+          )
+        ];
+        $element['form']['inline_entity_form']['#process'] = [
+          ['\Drupal\inline_entity_form\Element\InlineEntityForm', 'processEntityForm'],
+          [get_class($this), 'addIefSubmitCallbacks'],
+          [get_class($this), 'buildEntityFormActions'],
         ];
       }
       elseif ($form_state->get(['inline_entity_form', $this->getIefId(), 'form']) == 'ief_add_existing') {
@@ -521,7 +535,7 @@ class InlineEntityFormMultiple extends InlineEntityFormBase implements Container
           // Add the pre_render callback that powers the #fieldset form element key,
           // which moves the element to the specified fieldset without modifying its
           // position in $form_state->get('values').
-          '#pre_render' => ['inline_entity_form_pre_render_add_fieldset_markup'],
+          '#pre_render' => [[get_class($this), 'addFieldsetMarkup']],
         );
 
         $element['form'] += inline_entity_form_reference_form($this->iefHandler, $element['form'], $form_state);
@@ -648,17 +662,6 @@ class InlineEntityFormMultiple extends InlineEntityFormBase implements Container
   }
 
   /**
-   * Adds submit callbacks to the inline entity form.
-   *
-   * @param array $element
-   *   Form array structure.
-   */
-  public static function addIefSubmitCallbacks($element) {
-    $element['#ief_element_submit'][] = [get_called_class(), 'submitSaveEntity'];
-    return $element;
-  }
-
-  /**
    * Adds actions to the inline entity form.
    *
    * @param array $element
@@ -908,46 +911,6 @@ class InlineEntityFormMultiple extends InlineEntityFormBase implements Container
   }
 
   /**
-   * Marks created/edited entity with "needs save" flag.
-   *
-   * Note that at this point the entity is not yet saved, since the user might
-   * still decide to cancel the parent form.
-   *
-   * @param $entity_form
-   *  The form of the entity being managed inline.
-   * @param $form_state
-   *   The form state of the parent form.
-   */
-  public static function submitSaveEntity($entity_form, FormStateInterface $form_state) {
-    $ief_id = $entity_form['#ief_id'];
-    $entity = $entity_form['#entity'];
-
-    if ($entity_form['#op'] == 'add') {
-      // Determine the correct weight of the new element.
-      $weight = 0;
-      $entities = $form_state->get(['inline_entity_form', $ief_id, 'entities']);
-      if (!empty($entities)) {
-        $weight = max(array_keys($entities)) + 1;
-      }
-      // Add the entity to form state, mark it for saving, and close the form.
-      $entities[] = array(
-        'entity' => $entity,
-        '_weight' => $weight,
-        'form' => NULL,
-        'needs_save' => TRUE,
-      );
-      $form_state->set(['inline_entity_form', $ief_id, 'entities'], $entities);
-    }
-    else {
-      $delta = $entity_form['#ief_row_delta'];
-      $entities = $form_state->get(['inline_entity_form', $ief_id, 'entities']);
-      $entities[$delta]['entity'] = $entity;
-      $entities[$delta]['needs_save'] = TRUE;
-      $form_state->set(['inline_entity_form', $ief_id, 'entities'], $entities);
-    }
-  }
-
-  /**
    * Updates entity weights based on their weights in the widget.
    */
   public static function updateRowWeights($element, FormStateInterface $form_state, $form) {
diff --git a/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php b/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
new file mode 100644
index 0000000..fcf1a6c
--- /dev/null
+++ b/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
@@ -0,0 +1,164 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\inline_entity_form\Plugin\Field\FieldWidget\InlineEntityFormSimple.
+ */
+
+namespace Drupal\inline_entity_form\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Field\WidgetBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Single value widget.
+ *
+ * @FieldWidget(
+ *   id = "inline_entity_form_simple",
+ *   label = @Translation("Simple inline entity form"),
+ *   field_types = {
+ *     "entity_reference"
+ *   },
+ *   multiple_values = false
+ * )
+ */
+class InlineEntityFormSimple extends InlineEntityFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    if (!$this->canBuildForm($form_state)) {
+      return $element;
+    }
+
+    $this->setIefId(sha1($items->getName() . '-ief-single-' . $delta));
+    $entity_type = $this->getFieldSettings()['target_type'];
+
+    $element['#type'] = 'fieldset';
+    if ($items->get($delta)->target_id) {
+      $entity = $this->entityManager->getStorage($entity_type)->load($items->get($delta)->target_id);
+      if ($entity) {
+        $element['inline_entity_form'] = $this->getInlineEntityForm(
+          'edit',
+          $entity_type,
+          $items->getParent()->getValue()->language()->getId(),
+          $delta,
+          array_merge($element['#field_parents'], [
+            $items->getName(),
+            $delta,
+            'inline_entity_form'
+          ]),
+          reset($this->getFieldSettings()['handler_settings']['target_bundles']),
+          $entity,
+          TRUE
+        );
+      }
+      else {
+        $element['warning']['#markup'] = t('Unable to load referenced entity.');
+      }
+    }
+    else {
+      $element['inline_entity_form'] = $this->getInlineEntityForm(
+        'add',
+        $entity_type,
+        $items->getParent()->getValue()->language()->getId(),
+        $delta,
+        array_merge($element['#field_parents'], [
+          $items->getName(),
+          $delta,
+          'inline_entity_form'
+        ]),
+        reset($this->getFieldSettings()['handler_settings']['target_bundles']),
+        NULL,
+        TRUE
+      );
+    }
+    return $element;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
+    $element = parent::formMultipleElements($items, $form, $form_state);
+
+    // If we're using ulimited cardinality we don't display one empty item. Form
+    // validation will kick in if left empty which esentially means people won't
+    // be able to submit w/o creating another entity.
+    if ($element['#cardinality'] == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && $element['#max_delta'] > 0) {
+      $max = $element['#max_delta'];
+      unset($element[$max]);
+      $element['#max_delta'] = $max - 1;
+      $items->removeItem($max);
+    }
+
+    return $element;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
+    if ($this->isDefaultValueWidget($form_state)) {
+      $items->filterEmptyItems();
+      return;
+    }
+
+    $field_name = $this->fieldDefinition->getName();
+    $path = array_merge($form['#parents'], array($field_name));
+    $submitted_values = $form_state->getValue($path);
+
+    $values = [];
+    foreach ($items as $delta => $value) {
+      $this->setIefId(sha1($items->getName() . '-ief-single-' . $delta));
+
+      /** @var \Drupal\Core\Entity\EntityInterface $entity */
+      if (!$entity = $form_state->get(['inline_entity_form', $this->getIefId(), 'entity'])) {
+        return;
+      }
+
+      $values[$submitted_values[$delta]['_weight']] = ['entity' => $entity];
+    }
+
+    // Sort items base on weights.
+    ksort($values);
+    $values = array_values($values);
+
+    // Let the widget massage the submitted values.
+    $values = $this->massageFormValues($values, $form, $form_state);
+
+    // Assign the values and remove the empty ones.
+    $items->setValue($values);
+    $items->filterEmptyItems();
+
+    // Put delta mapping in $form_state, so that flagErrors() can use it.
+    $field_name = $this->fieldDefinition->getName();
+    $field_state = WidgetBase::getWidgetState($form['#parents'], $field_name, $form_state);
+    foreach ($items as $delta => $item) {
+      $field_state['original_deltas'][$delta] = isset($item->_original_delta) ? $item->_original_delta : $delta;
+      unset($item->_original_delta, $item->_weight);
+    }
+
+    WidgetBase::setWidgetState($form['#parents'], $field_name, $form_state, $field_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function isApplicable(FieldDefinitionInterface $field_definition) {
+    if (!$field_definition->isRequired()) {
+      return FALSE;
+    }
+
+    if (count($field_definition->getSettings()['handler_settings']['target_bundles']) != 1) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+
+}
diff --git a/src/Plugin/Field/FieldWidget/InlineEntityFormSingle.php b/src/Plugin/Field/FieldWidget/InlineEntityFormSingle.php
deleted file mode 100644
index f255e39..0000000
--- a/src/Plugin/Field/FieldWidget/InlineEntityFormSingle.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\inline_entity_form\Plugin\Field\FieldWidget\InlineEntityFormSingle.
- */
-
-namespace Drupal\inline_entity_form\Plugin\Field\FieldWidget;
-
-use Drupal\Core\Field\FieldItemListInterface;
-use Drupal\Core\Field\WidgetBase;
-use Drupal\Core\Form\FormStateInterface;
-
-/**
- * Single value widget.
- *
- * @FieldWidget(
- *   id = "inline_entity_form_single",
- *   label = @Translation("Inline entity form - Single value"),
- *   field_types = {
- *     "entity_reference"
- *   },
- *   multiple_values = false
- * )
- */
-class InlineEntityFormSingle extends InlineEntityFormBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
-    $ief_id = $this->fieldDefinition;
-
-    return $element;
-  }
-
-}
diff --git a/src/Tests/CustomFormTest.php b/src/Tests/CustomFormTest.php
deleted file mode 100644
index b5378aa..0000000
--- a/src/Tests/CustomFormTest.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\inline_entity_form\Tests\CustomFormTest.
- */
-
-namespace Drupal\inline_entity_form\Tests;
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests the IEF element on a custom form.
- *
- * @group inline_entity_form
- */
-class CustomFormTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['inline_entity_form_test'];
-
-  /**
-   * Tests IEF on a custom form.
-   */
-  public function testDisplayPluginAlterHooks() {
-    $this->drupalGet('ief-test');
-    $this->assertText(t('Title'), 'Title field found on the form.');
-
-    $edit = ['inline_entity_form[title][0][value]' => $this->randomString()];
-    $this->drupalPostForm('ief-test', $edit, t('Save'));
-    $message = t('Created @entity_type @label.', ['@entity_type' => t('Content'), '@label' => $edit['inline_entity_form[title][0][value]']]);
-    $this->assertText($message, 'Status message found on the page.');
-
-    /** @var \Drupal\node\NodeInterface $node */
-    $node = $this->container->get('entity.manager')->getStorage('node')->load(1);
-    $this->assertEqual($node->label(), $edit['inline_entity_form[title][0][value]'], 'Node title correctly saved to the database.');
-    $this->assertEqual($node->bundle(), 'ief_test', 'Correct bundle used when creating the new node.');
-  }
-
-}
diff --git a/src/Tests/InlineEntityFormWebTest.php b/src/Tests/InlineEntityFormWebTest.php
new file mode 100644
index 0000000..e87c8fc
--- /dev/null
+++ b/src/Tests/InlineEntityFormWebTest.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\inline_entity_form\Tests\InlineEntityFormWebTest.
+ */
+
+namespace Drupal\inline_entity_form\Tests;
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests the IEF element on a custom form.
+ *
+ * @group inline_entity_form
+ */
+class InlineEntityFormWebTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['inline_entity_form_test'];
+
+  /**
+   * User with permissions to create content.
+   *
+   * @var \Drupal\user\Entity\User
+   */
+  protected $user;
+  /**
+   * Prepares environment for
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->user = $this->createUser([
+      'create ief_simple_single content',
+      'edit any ief_simple_single content',
+      'edit any ief_test_custom content',
+      'view own unpublished content',
+    ]);
+  }
+
+  /**
+   * Tests IEF on a custom form.
+   */
+  public function testCustomFormIEF() {
+    $this->drupalGet('ief-test');
+    $this->assertText(t('Title'), 'Title field found on the form.');
+
+    $edit = ['inline_entity_form[title][0][value]' => $this->randomString()];
+    $this->drupalPostForm('ief-test', $edit, t('Save'));
+    $message = t('Created @entity_type @label.', ['@entity_type' => t('Content'), '@label' => $edit['inline_entity_form[title][0][value]']]);
+    $this->assertText($message, 'Status message found on the page.');
+
+    /** @var \Drupal\node\NodeInterface $node */
+    $node = $this->container->get('entity.manager')->getStorage('node')->load(1);
+    $this->assertEqual($node->label(), $edit['inline_entity_form[title][0][value]'], 'Node title correctly saved to the database.');
+    $this->assertEqual($node->bundle(), 'ief_test_custom', 'Correct bundle used when creating the new node.');
+  }
+
+  /**
+   * Tests simple IEF widget with single-value field.
+   */
+  public function testSimpleSingle() {
+    $this->drupalLogin($this->user);
+    $this->drupalGet('node/add/ief_simple_single');
+
+    $this->assertText('Single node', 'Inline entity field widget title found.');
+    $this->assertText('Reference a single node.', 'Inline entity field description found.');
+
+    $edit = [
+      'title[0][value]' => 'Host node',
+      'single[0][inline_entity_form][title][0][value]' => 'Child node',
+    ];
+    $this->drupalPostForm('node/add/ief_simple_single', $edit, t('Save'));
+  }
+
+}
diff --git a/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test.default.yml b/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_single.default.yml
similarity index 69%
copy from tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test.default.yml
copy to tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_single.default.yml
index e09b7f4..8120caa 100644
--- a/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test.default.yml
+++ b/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_single.default.yml
@@ -2,10 +2,10 @@ langcode: und
 status: true
 dependencies:
   config:
-    - node.type.ief_test
-id: node.ief_test.default
+    - node.type.ief_simple_single
+id: node.ief_simple_single.default
 targetEntityType: node
-bundle: ief_test
+bundle: ief_simple_single
 mode: default
 content:
   title:
@@ -40,4 +40,14 @@ content:
       size: 60
       placeholder: ''
     third_party_settings: {  }
+  single:
+    weight: 30
+    settings:
+      match_operator: CONTAINS
+      allow_existing: false
+      override_labels: false
+      label_singular: ''
+      label_plural: ''
+    third_party_settings: {  }
+    type: inline_entity_form_simple
 hidden: {  }
diff --git a/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test.default.yml b/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_custom.default.yml
similarity index 89%
rename from tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test.default.yml
rename to tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_custom.default.yml
index e09b7f4..f4d8e51 100644
--- a/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test.default.yml
+++ b/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_custom.default.yml
@@ -2,10 +2,10 @@ langcode: und
 status: true
 dependencies:
   config:
-    - node.type.ief_test
-id: node.ief_test.default
+    - node.type.ief_test_custom
+id: node.ief_test_custom.default
 targetEntityType: node
-bundle: ief_test
+bundle: ief_test_custom
 mode: default
 content:
   title:
diff --git a/tests/modules/inline_entity_form_test/config/install/field.field.node.ief_simple_single.single.yml b/tests/modules/inline_entity_form_test/config/install/field.field.node.ief_simple_single.single.yml
new file mode 100644
index 0000000..eb39575
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/install/field.field.node.ief_simple_single.single.yml
@@ -0,0 +1,31 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.single
+    - node.type.ief_simple_single
+  module:
+    - inline_entity_form_test
+    - entity_reference
+  enforced:
+    module:
+      - inline_entity_form_test
+id: node.ief_simple_single.single
+field_name: single
+entity_type: node
+bundle: ief_simple_single
+label: Single node
+description: 'Reference a single node.'
+required: true
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: default
+  handler_settings:
+    target_bundles:
+      article: ief_test_custom
+    sort:
+      field: _none
+third_party_settings: {  }
+field_type: entity_reference
diff --git a/tests/modules/inline_entity_form_test/config/install/field.storage.node.multi.yml b/tests/modules/inline_entity_form_test/config/install/field.storage.node.multi.yml
new file mode 100644
index 0000000..57347b1
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/install/field.storage.node.multi.yml
@@ -0,0 +1,22 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - inline_entity_form_test
+    - entity_reference
+    - node
+  enforced:
+    module:
+      - inline_entity_form_test
+id: node.multi
+field_name: multi
+entity_type: node
+type: entity_reference
+settings:
+  target_type: node
+module: entity_reference
+locked: false
+cardinality: -1
+translatable: false
+indexes: {  }
+persist_with_no_fields: false
diff --git a/tests/modules/inline_entity_form_test/config/install/field.storage.node.single.yml b/tests/modules/inline_entity_form_test/config/install/field.storage.node.single.yml
new file mode 100644
index 0000000..3954bad
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/install/field.storage.node.single.yml
@@ -0,0 +1,22 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - inline_entity_form_test
+    - entity_reference
+    - node
+  enforced:
+    module:
+      - inline_entity_form_test
+id: node.single
+field_name: single
+entity_type: node
+type: entity_reference
+settings:
+  target_type: node
+module: entity_reference
+locked: false
+cardinality: 1
+translatable: false
+indexes: {  }
+persist_with_no_fields: false
diff --git a/tests/modules/inline_entity_form_test/config/install/node.type.ief_simple_single.yml b/tests/modules/inline_entity_form_test/config/install/node.type.ief_simple_single.yml
new file mode 100644
index 0000000..184c40a
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/install/node.type.ief_simple_single.yml
@@ -0,0 +1,9 @@
+type: ief_simple_single
+name: IEF single simple
+description: 'Content type for testing simple IEF widget on a single-value field.'
+help: ''
+new_revision: false
+preview_mode: 1
+display_submitted: false
+status: true
+langcode: und
diff --git a/tests/modules/inline_entity_form_test/config/install/node.type.ief_test.yml b/tests/modules/inline_entity_form_test/config/install/node.type.ief_test.yml
deleted file mode 100644
index 4534cf4..0000000
--- a/tests/modules/inline_entity_form_test/config/install/node.type.ief_test.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-type: ief_test
-name: IEF test
-description: 'Content type for IEF testing.'
-help: ''
-new_revision: false
-preview_mode: 1
-display_submitted: false
-status: true
-langcode: und
diff --git a/tests/modules/inline_entity_form_test/config/install/node.type.ief_test_custom.yml b/tests/modules/inline_entity_form_test/config/install/node.type.ief_test_custom.yml
new file mode 100644
index 0000000..c1808a9
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/install/node.type.ief_test_custom.yml
@@ -0,0 +1,9 @@
+type: ief_test_custom
+name: IEF test cestim
+description: 'Content type for IEF custom form testing.'
+help: ''
+new_revision: false
+preview_mode: 1
+display_submitted: false
+status: true
+langcode: und
diff --git a/tests/modules/inline_entity_form_test/inline_entity_form_test.info.yml b/tests/modules/inline_entity_form_test/inline_entity_form_test.info.yml
index e410f07..d36ca16 100644
--- a/tests/modules/inline_entity_form_test/inline_entity_form_test.info.yml
+++ b/tests/modules/inline_entity_form_test/inline_entity_form_test.info.yml
@@ -5,5 +5,6 @@ core: 8.x
 package: Testing
 version: VERSION
 dependencies:
+  - entity_reference
   - inline_entity_form
   - node
diff --git a/tests/modules/inline_entity_form_test/src/IefTest.php b/tests/modules/inline_entity_form_test/src/IefTest.php
index e6712f5..09d3d94 100644
--- a/tests/modules/inline_entity_form_test/src/IefTest.php
+++ b/tests/modules/inline_entity_form_test/src/IefTest.php
@@ -30,7 +30,7 @@ class IefTest extends FormBase {
       '#type' => 'inline_entity_form',
       '#op' => 'add',
       '#entity_type' => 'node',
-      '#bundle' => 'ief_test',
+      '#bundle' => 'ief_test_custom',
     ];
     $form['submit'] = [
       '#type' => 'submit',
