diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php
index 7b3a74b..c7796c4 100644
--- a/core/lib/Drupal/Core/Config/ConfigManager.php
+++ b/core/lib/Drupal/Core/Config/ConfigManager.php
@@ -413,12 +413,12 @@ protected function callOnDependencyRemoval(ConfigEntityInterface $entity, array
       if ($type == 'config' || $type == 'content') {
         $affected_dependencies[$type] = array_map(function ($name) use ($type) {
           if ($type == 'config') {
-            $entity_type_id = $this->getEntityTypeIdByName($name);
+            return $this->loadConfigEntityByName($name);
           }
           else {
             list($entity_type_id) = explode(':', $name);
+            return $this->entityManager->loadEntityByConfigTarget($entity_type_id, $name);
           }
-          return $this->entityManager->loadEntityByConfigTarget($entity_type_id, $name);
         }, $affected_dependencies[$type]);
       }
     }
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyDeleteFormTrait.php b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyDeleteFormTrait.php
new file mode 100644
index 0000000..ada9ac3
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyDeleteFormTrait.php
@@ -0,0 +1,130 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Config\Entity\ConfigDependencyDeleteFormTrait;
+ */
+
+
+namespace Drupal\Core\Config\Entity;
+
+use Drupal\Core\Config\ConfigManagerInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
+
+/**
+ * Lists affected configuration entities by a dependency removal.
+ *
+ * This trait relies on the StringTranslationTrait.
+ */
+trait ConfigDependencyDeleteFormTrait {
+
+  /**
+   * Translates a string to the current language or to a given language.
+   *
+   * Provided by \Drupal\Core\StringTranslation\StringTranslationTrait.
+   */
+  abstract protected function t($string, array $args = array(), array $options = array());
+
+  /**
+   * Adds form elements to list affected configuration entities.
+   *
+   * @param array $form
+   *   The form array to add elements to.
+   * @param string $type
+   *   The type of dependency being checked. Either 'module', 'theme', 'config'
+   *   or 'content'.
+   * @param array $names
+   *   The specific names to check. If $type equals 'module' or 'theme' then it
+   *   should be a list of module names or theme names. In the case of 'config'
+   *   or 'content' it should be a list of configuration dependency names.
+   * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
+   *   The config manager.
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   *
+   * @see \Drupal\Core\Config\ConfigManagerInterface::getConfigEntitiesToChangeOnDependencyRemoval()
+   */
+  protected function addDependencyListsToForm(array &$form, $type, array $names, ConfigManagerInterface $config_manager, EntityManagerInterface $entity_manager) {
+    // Get the dependent entities.
+    $dependent_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval($type, $names);
+    $entity_types = array();
+
+    $form['entity_updates'] = array(
+      '#type' => 'details',
+      '#title' => $this->t('Configuration updates'),
+      '#description' => $this->t('The listed configuration will be updated.'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#access' => FALSE,
+    );
+
+    foreach ($dependent_entities['update'] as $entity) {
+      /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface  $entity */
+      $entity_type_id = $entity->getEntityTypeId();
+      if (!isset($form['entity_updates'][$entity_type_id])) {
+        $entity_type = $entity_manager->getDefinition($entity_type_id);
+        // Store the ID and label to sort the entity types and entities later.
+        $label = $entity_type->getLabel();
+        $entity_types[$entity_type_id] = $label;
+        $form['entity_updates'][$entity_type_id] = array(
+          '#theme' => 'item_list',
+          '#title' => $label,
+          '#items' => array(),
+        );
+      }
+      $form['entity_updates'][$entity_type_id]['#items'][] = $entity->label() ?: $entity->id();
+    }
+    if (!empty($dependent_entities['update'])) {
+      $form['entity_updates']['#access'] = TRUE;
+
+      // Add a weight key to the entity type sections.
+      asort($entity_types, SORT_FLAG_CASE);
+      $weight = 0;
+      foreach ($entity_types as $entity_type_id => $label) {
+        $form['entity_updates'][$entity_type_id]['#weight'] = $weight;
+        // Sort the list of entity labels alphabetically.
+        sort($form['entity_updates'][$entity_type_id]['#items'], SORT_FLAG_CASE);
+        $weight++;
+      }
+    }
+
+    $form['entity_deletes'] = array(
+      '#type' => 'details',
+      '#title' => $this->t('Configuration deletions'),
+      '#description' => $this->t('The listed configuration will be deleted.'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#access' => FALSE,
+    );
+
+    foreach ($dependent_entities['delete'] as $entity) {
+      $entity_type_id = $entity->getEntityTypeId();
+      if (!isset($form['entity_deletes'][$entity_type_id])) {
+        $entity_type = $entity_manager->getDefinition($entity_type_id);
+        // Store the ID and label to sort the entity types and entities later.
+        $label = $entity_type->getLabel();
+        $entity_types[$entity_type_id] = $label;
+        $form['entity_deletes'][$entity_type_id] = array(
+          '#theme' => 'item_list',
+          '#title' => $label,
+          '#items' => array(),
+        );
+      }
+      $form['entity_deletes'][$entity_type_id]['#items'][] = $entity->label() ?: $entity->id();
+    }
+    if (!empty($dependent_entities['delete'])) {
+      $form['entity_deletes']['#access'] = TRUE;
+
+      // Add a weight key to the entity type sections.
+      asort($entity_types, SORT_FLAG_CASE);
+      $weight = 0;
+      foreach ($entity_types as $entity_type_id => $label) {
+        $form['entity_deletes'][$entity_type_id]['#weight'] = $weight;
+        // Sort the list of entity labels alphabetically.
+        sort($form['entity_deletes'][$entity_type_id]['#items'], SORT_FLAG_CASE);
+        $weight++;
+      }
+    }
+
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
index 7d684e0..d4bbbaa 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Config\ConfigException;
 use Drupal\Core\Config\Schema\SchemaIncompleteException;
 use Drupal\Core\Entity\Entity;
 use Drupal\Core\Config\ConfigDuplicateUUIDException;
@@ -233,7 +234,8 @@ public function createDuplicate() {
   }
 
   /**
-   * Helper callback for uasort() to sort configuration entities by weight and label.
+   * Helper callback for uasort() to sort configuration entities by weight and
+   * label.
    */
   public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) {
     $a_weight = isset($a->weight) ? $a->weight : 0;
@@ -517,4 +519,36 @@ public function getThirdPartyProviders() {
     return array_keys($this->third_party_settings);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function preDelete(EntityStorageInterface $storage, array $entities) {
+    foreach ($entities as $entity) {
+      if ($entity->isUninstalling() || $entity->isSyncing()) {
+        // During extension uninstall and configuration synchronization
+        // deletions are already managed.
+        break;
+      }
+      // Fix or remove any dependencies.
+      $config_entities = static::getConfigManager()->getConfigEntitiesToChangeOnDependencyRemoval('config', [$entity->getConfigDependencyName()], FALSE);
+      /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $dependent_entity */
+      foreach ($config_entities['update'] as $dependent_entity) {
+        $dependent_entity->save();
+      }
+      foreach ($config_entities['delete'] as $dependent_entity) {
+        $dependent_entity->delete();
+      }
+    }
+  }
+
+  /**
+   * Gets the configuration manager.
+   *
+   * @return \Drupal\Core\Config\ConfigManager
+   *   The configuration manager.
+   */
+  protected static function getConfigManager() {
+    return \Drupal::service('config.manager');
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
index 1db3b42..86095c7 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
@@ -165,10 +165,6 @@ public function calculateDependencies();
    * caller for the changes to take effect. Implementations should not save the
    * entity.
    *
-   * @todo https://www.drupal.org/node/2336727 this method is only fired during
-   *   extension uninstallation but it could be used during config entity
-   *   deletion too.
-   *
    * @param array $dependencies
    *   An array of dependencies that will be deleted keyed by dependency type.
    *   Dependency types are, for example, entity, module and theme.
@@ -176,7 +172,11 @@ public function calculateDependencies();
    * @return bool
    *   TRUE if the entity has changed, FALSE if not.
    *
+   * @return bool
+   *   TRUE if the entity has been changed as a result, FALSE if not.
+   *
    * @see \Drupal\Core\Config\Entity\ConfigDependencyManager
+   * @see \Drupal\Core\Config\ConfigEntityBase::preDelete()
    * @see \Drupal\Core\Config\ConfigManager::uninstall()
    * @see \Drupal\Core\Entity\EntityDisplayBase::onDependencyRemoval()
    */
diff --git a/core/lib/Drupal/Core/Entity/EntityDeleteForm.php b/core/lib/Drupal/Core/Entity/EntityDeleteForm.php
index 71560a2..7869af8 100644
--- a/core/lib/Drupal/Core/Entity/EntityDeleteForm.php
+++ b/core/lib/Drupal/Core/Entity/EntityDeleteForm.php
@@ -7,13 +7,45 @@
 
 namespace Drupal\Core\Entity;
 
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Form\FormStateInterface;
+
 /**
  * Provides a generic base class for an entity deletion form.
  *
  * @ingroup entity_api
  */
 class EntityDeleteForm extends EntityConfirmFormBase {
-
   use EntityDeleteFormTrait;
 
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form = parent::buildForm($form, $form_state);
+    $entity = $this->getEntity();
+    // Only do dependency processing for configuration entities. Whilst it is
+    // possible for a configuration entity to be dependent on a content entity,
+    // these dependencies are soft and content delete permissions are often
+    // given to more users. This method should not make assumptions that $entity
+    // is a configuration entity in case we decide to remove the following
+    // condition.
+    if (!($entity instanceof ConfigEntityInterface)) {
+      return $form;
+    }
+    $this->addDependencyListsToForm($form, $entity->getConfigDependencyKey(), [$entity->getConfigDependencyName()], $this->getConfigManager(), $this->entityManager);
+
+    return $form;
+  }
+
+  /**
+   * Gets the configuration manager.
+   *
+   * @return \Drupal\Core\Config\ConfigManager
+   *   The configuration manager.
+   */
+  protected function getConfigManager() {
+    return \Drupal::service('config.manager');
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityDeleteFormTrait.php b/core/lib/Drupal/Core/Entity/EntityDeleteFormTrait.php
index 80bb50d..7e4ce04 100644
--- a/core/lib/Drupal/Core/Entity/EntityDeleteFormTrait.php
+++ b/core/lib/Drupal/Core/Entity/EntityDeleteFormTrait.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Entity;
 
+use Drupal\Core\Config\Entity\ConfigDependencyDeleteFormTrait;
 use Drupal\Core\Form\FormStateInterface;
 
 /**
@@ -18,13 +19,7 @@
  * @ingroup entity_api
  */
 trait EntityDeleteFormTrait {
-
-  /**
-   * Translates a string to the current language or to a given language.
-   *
-   * Provided by \Drupal\Core\StringTranslation\StringTranslationTrait.
-   */
-  abstract protected function t($string, array $args = array(), array $options = array());
+  use ConfigDependencyDeleteFormTrait;
 
   /**
    * Returns the entity of this form.
diff --git a/core/lib/Drupal/Core/Field/FieldConfigBase.php b/core/lib/Drupal/Core/Field/FieldConfigBase.php
index 7388b4b..026570f 100644
--- a/core/lib/Drupal/Core/Field/FieldConfigBase.php
+++ b/core/lib/Drupal/Core/Field/FieldConfigBase.php
@@ -264,6 +264,20 @@ public function calculateDependencies() {
   /**
    * {@inheritdoc}
    */
+  public function onDependencyRemoval(array $dependencies) {
+    $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
+    $definition = $field_type_manager->getDefinition($this->getType());
+    $changed = $definition['class']::onDependencyRemoval($this, $dependencies);
+    if ($changed) {
+      $this->save();
+    }
+    return $changed;
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
   public function postCreate(EntityStorageInterface $storage) {
     parent::postCreate($storage);
     // If it was not present in the $values passed to create(), (e.g. for
diff --git a/core/lib/Drupal/Core/Field/FieldItemBase.php b/core/lib/Drupal/Core/Field/FieldItemBase.php
index b411b88..b2119e3 100644
--- a/core/lib/Drupal/Core/Field/FieldItemBase.php
+++ b/core/lib/Drupal/Core/Field/FieldItemBase.php
@@ -273,4 +273,11 @@ public static function calculateDependencies(FieldDefinitionInterface $field_def
     return array();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function onDependencyRemoval(FieldDefinitionInterface $field_definition, array $dependencies) {
+    return FALSE;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Field/FieldItemInterface.php
index 1d0de29..f74b3f7 100644
--- a/core/lib/Drupal/Core/Field/FieldItemInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldItemInterface.php
@@ -405,4 +405,20 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state);
    */
   public static function calculateDependencies(FieldDefinitionInterface $field_definition);
 
+  /**
+   * Informs the plugin that a dependency of the field will be deleted.
+   *
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   The field definition.
+   * @param array $dependencies
+   *   An array of dependencies that will be deleted keyed by dependency type.
+   *   Dependency types are, for example, entity, module and theme.
+   *
+   * @return bool
+   *   TRUE if the field definition has been changed as a result, FALSE if not.
+   *
+   * @see \Drupal\Core\Config\ConfigEntityInterface::onDependencyRemoval()
+   */
+  public static function onDependencyRemoval(FieldDefinitionInterface $field_definition, array $dependencies);
+
 }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
index e03750d..10497ad 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -286,4 +286,26 @@ public static function calculateDependencies(FieldDefinitionInterface $field_def
     return $dependencies;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function onDependencyRemoval(FieldDefinitionInterface $field_definition, array $dependencies) {
+    $changed = FALSE;
+    if (is_array($field_definition->default_value) && count($field_definition->default_value)) {
+      $target_entity_type = \Drupal::entityManager()->getDefinition($field_definition->getFieldStorageDefinition()->getSetting('target_type'));
+      foreach ($field_definition->default_value as $default_value) {
+        if (is_array($default_value) && isset($default_value['target_uuid'])) {
+          $entity = \Drupal::entityManager()->loadEntityByUuid($target_entity_type->id(), $default_value['target_uuid']);
+          // If the entity does not exist do not create the dependency.
+          // @see \Drupal\Core\Field\EntityReferenceFieldItemList::processDefaultValue()
+          if ($entity && in_array($entity, $dependencies[$target_entity_type->getConfigDependencyKey()])) {
+            $field_definition->default_value = [];
+            $changed = TRUE;
+          }
+        }
+      }
+    }
+    return $changed;
+  }
+
 }
diff --git a/core/modules/config/src/Tests/ConfigDependencyTest.php b/core/modules/config/src/Tests/ConfigDependencyTest.php
index 047a20d..c78eaac 100644
--- a/core/modules/config/src/Tests/ConfigDependencyTest.php
+++ b/core/modules/config/src/Tests/ConfigDependencyTest.php
@@ -273,6 +273,106 @@ public function testConfigEntityUninstall() {
   }
 
   /**
+   * Tests deleting a configuration entity and dependency management.
+   */
+  public function testConfigEntityDelete() {
+    /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
+    $config_manager = \Drupal::service('config.manager');
+    /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $storage */
+    $storage = $this->container->get('entity.manager')->getStorage('config_test');
+    // Test dependencies between configuration entities.
+    $entity1 = $storage->create(
+      array(
+        'id' => 'entity1'
+      )
+    );
+    $entity1->save();
+    $entity2 = $storage->create(
+      array(
+        'id' => 'entity2',
+        'dependencies' => array(
+          'enforced' => array(
+            'config' => array($entity1->getConfigDependencyName()),
+          ),
+        ),
+      )
+    );
+    $entity2->save();
+
+    // Do a dry run using
+    // \Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval().
+    $config_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval('config', [$entity1->getConfigDependencyName()]);
+    $this->assertEqual($entity2->uuid(), reset($config_entities['delete'])->uuid(), 'Entity 2 will be deleted.');
+    $this->assertTrue(empty($config_entities['update']), 'No dependent configuration entities will be updated.');
+    $this->assertTrue(empty($config_entities['unchanged']), 'No dependent configuration entities will be unchanged.');
+
+    // Test that doing a delete of entity1 deletes entity2 since it is dependent
+    // on entity1.
+    $entity1->delete();
+    $this->assertFalse($storage->load('entity1'), 'Entity 1 deleted');
+    $this->assertFalse($storage->load('entity2'), 'Entity 2 deleted');
+
+    // Set a more complicated test where dependencies will be fixed.
+    \Drupal::state()->set('config_test.fix_dependencies', array($entity1->getConfigDependencyName()));
+
+    // Entity1 will be deleted by the test.
+    $entity1 = $storage->create(
+      array(
+        'id' => 'entity1',
+      )
+    );
+    $entity1->save();
+
+    // Entity2 has a dependency on Entity1 but it can be fixed because
+    // \Drupal\config_test\Entity::onDependencyRemoval() will remove the
+    // dependency before config entities are deleted.
+    $entity2 = $storage->create(
+      array(
+        'id' => 'entity2',
+        'dependencies' => array(
+          'enforced' => array(
+            'config' => array($entity1->getConfigDependencyName()),
+          ),
+        ),
+      )
+    );
+    $entity2->save();
+
+    // Entity3 will be unchanged because it is dependent on Entity2 which can
+    // be fixed.
+    $entity3 = $storage->create(
+      array(
+        'id' => 'entity3',
+        'dependencies' => array(
+          'enforced' => array(
+            'config' => array($entity2->getConfigDependencyName()),
+          ),
+        ),
+      )
+    );
+    $entity3->save();
+
+    // Do a dry run using
+    // \Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval().
+    $config_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval('config', [$entity1->getConfigDependencyName()]);
+    $this->assertTrue(empty($config_entities['delete']), 'No dependent configuration entities will be deleted.');
+    $this->assertEqual($entity2->uuid(), reset($config_entities['update'])->uuid(), 'Entity 2 will be updated.');
+    $this->assertEqual($entity3->uuid(), reset($config_entities['unchanged'])->uuid(), 'Entity 3 is not changed.');
+
+    // Perform the uninstall.
+    $entity1->delete();
+
+    // Test that expected actions have been performed.
+    $this->assertFalse($storage->load('entity1'), 'Entity 1 deleted');
+    $entity2 = $storage->load('entity2');
+    $this->assertTrue($entity2, 'Entity 2 not deleted');
+    $this->assertEqual($entity2->calculateDependencies()['config'], array(), 'Entity 2 dependencies updated to remove dependency on Entity1.');
+    $entity3 = $storage->load('entity3');
+    $this->assertTrue($entity3, 'Entity 3 not deleted');
+    $this->assertEqual($entity3->calculateDependencies()['config'], [$entity2->getConfigDependencyName()], 'Entity 3 still depends on Entity 2.');
+  }
+
+  /**
    * Tests getConfigEntitiesToChangeOnDependencyRemoval() with content entities.
    *
    * At the moment there is no runtime code that calculates configuration
diff --git a/core/modules/config/src/Tests/ConfigDependencyWebTest.php b/core/modules/config/src/Tests/ConfigDependencyWebTest.php
new file mode 100644
index 0000000..019c8cb
--- /dev/null
+++ b/core/modules/config/src/Tests/ConfigDependencyWebTest.php
@@ -0,0 +1,133 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\config\Tests\ConfigDependencyWebTest.
+ */
+
+namespace Drupal\config\Tests;
+
+use Drupal\Core\Config\Entity\ConfigEntityStorage;
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests configuration entities.
+ *
+ * @group config
+ */
+class ConfigDependencyWebTest extends WebTestBase {
+
+  /**
+   * The maximum length for the entity storage used in this test.
+   */
+  const MAX_ID_LENGTH = ConfigEntityStorage::MAX_ID_LENGTH;
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('config_test');
+
+  /**
+   * Tests ConfigDependencyDeleteFormTrait.
+   *
+   * @see \Drupal\Core\Config\Entity\ConfigDependencyDeleteFormTrait
+   */
+  function testConfigDependencyDeleteFormTrait() {
+    /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $storage */
+    $storage = $this->container->get('entity.manager')->getStorage('config_test');
+    // Entity1 will be deleted by the test.
+    $entity1 = $storage->create(
+      array(
+        'id' => 'entity1',
+        'label' => 'Entity One',
+      )
+    );
+    $entity1->save();
+
+    // Entity2 has a dependency on Entity1 but it can be fixed because
+    // \Drupal\config_test\Entity::onDependencyRemoval() will remove the
+    // dependency before config entities are deleted.
+    $entity2 = $storage->create(
+      array(
+        'id' => 'entity2',
+        'dependencies' => array(
+          'enforced' => array(
+            'config' => array($entity1->getConfigDependencyName()),
+          ),
+        ),
+      )
+    );
+    $entity2->save();
+
+    $this->drupalGet($entity2->url('delete-form'));
+    $this->assertNoText(t('Configuration updates'), 'No configuration updates found.');
+    $this->assertNoText(t('Configuration deletions'), 'No configuration deletes found.');
+    $this->drupalGet($entity1->url('delete-form'));
+    $this->assertNoText(t('Configuration updates'), 'No configuration updates found.');
+    $this->assertText(t('Configuration deletions'), 'Configuration deletions found.');
+    $this->assertText($entity2->id(), 'Entity2 id found');
+    $this->drupalPostForm($entity1->url('delete-form'), array(), 'Delete');
+    $storage->resetCache();
+    $this->assertFalse($storage->loadMultiple([$entity1->id(), $entity2->id()]), 'Test entities deleted');
+
+    // Set a more complicated test where dependencies will be fixed.
+    // Entity1 will be deleted by the test.
+    $entity1 = $storage->create(
+      array(
+        'id' => 'entity1',
+      )
+    );
+    $entity1->save();
+    \Drupal::state()->set('config_test.fix_dependencies', array($entity1->getConfigDependencyName()));
+
+    // Entity2 has a dependency on Entity1 but it can be fixed because
+    // \Drupal\config_test\Entity::onDependencyRemoval() will remove the
+    // dependency before config entities are deleted.
+    $entity2 = $storage->create(
+      array(
+        'id' => 'entity2',
+        'label' => 'Entity Two',
+        'dependencies' => array(
+          'enforced' => array(
+            'config' => array($entity1->getConfigDependencyName()),
+          ),
+        ),
+      )
+    );
+    $entity2->save();
+
+    // Entity3 will be unchanged because it is dependent on Entity2 which can
+    // be fixed.
+    $entity3 = $storage->create(
+      array(
+        'id' => 'entity3',
+        'dependencies' => array(
+          'enforced' => array(
+            'config' => array($entity2->getConfigDependencyName()),
+          ),
+        ),
+      )
+    );
+    $entity3->save();
+
+    $this->drupalGet($entity1->url('delete-form'));
+    $this->assertText(t('Configuration updates'), 'Configuration updates found.');
+    $this->assertNoText(t('Configuration deletions'), 'No configuration deletions found.');
+    $this->assertNoText($entity2->id(), 'Entity2 id not found');
+    $this->assertText($entity2->label(), 'Entity2 label not found');
+    $this->assertNoText($entity3->id(), 'Entity3 id not found');
+    $this->drupalPostForm($entity1->url('delete-form'), array(), 'Delete');
+    $storage->resetCache();
+    $this->assertFalse($storage->load('entity1'), 'Test entity 1 deleted');
+    $entity2 = $storage->load('entity2');
+    $this->assertTrue($entity2, 'Entity 2 not deleted');
+    $this->assertEqual($entity2->calculateDependencies()['config'], array(), 'Entity 2 dependencies updated to remove dependency on Entity1.');
+    $entity3 = $storage->load('entity3');
+    $this->assertTrue($entity3, 'Entity 3 not deleted');
+    $this->assertEqual($entity3->calculateDependencies()['config'], [$entity2->getConfigDependencyName()], 'Entity 3 still depends on Entity 2.');
+
+  }
+
+}
diff --git a/core/modules/config/src/Tests/ConfigImporterTest.php b/core/modules/config/src/Tests/ConfigImporterTest.php
index d2c7cf0..bfef3a8 100644
--- a/core/modules/config/src/Tests/ConfigImporterTest.php
+++ b/core/modules/config/src/Tests/ConfigImporterTest.php
@@ -381,6 +381,10 @@ function testSecondaryUpdateDeletedDeleterFirst() {
 
   /**
    * Tests that secondary updates for deleted files work as expected.
+   *
+   * This test is completely hypothetical since we only support full
+   * configuration tree imports. Therefore, any configuration updates that cause
+   * secondary deletes should be reflected already in the staged configuration.
    */
   function testSecondaryUpdateDeletedDeleteeFirst() {
     $name_deleter = 'config_test.dynamic.deleter';
@@ -416,10 +420,10 @@ function testSecondaryUpdateDeletedDeleteeFirst() {
     $this->configImporter->reset()->import();
 
     $entity_storage = \Drupal::entityManager()->getStorage('config_test');
-    $deleter = $entity_storage->load('deleter');
-    $this->assertEqual($deleter->id(), 'deleter');
-    $this->assertEqual($deleter->uuid(), $values_deleter['uuid']);
-    $this->assertEqual($deleter->label(), $values_deleter['label']);
+    // Both entities are deleted. ConfigTest::postSave() causes updates of the
+    // deleter entity to delete the deletee entity. Since the deleter depends on
+    // the deletee, removing the deletee causes the deleter to be removed.
+    $this->assertFalse($entity_storage->load('deleter'));
     // @todo The deletee entity does not exist as the update worked but the
     //   entity was deleted after that. There is also no log message as this
     //   happened outside of the config importer.
diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php
index cabaf22..2203fd8 100644
--- a/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php
+++ b/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\config\Tests\AssertConfigEntityImportTrait;
+use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\simpletest\WebTestBase;
 
@@ -152,6 +153,9 @@ public function testSupportedEntityTypesAndWidgets() {
       // Ensure that the field can be imported without change even after the
       // default value deleted.
       $referenced_entities[0]->delete();
+      // Reload the field since deleting the default value can change the field.
+      \Drupal::entityManager()->getStorage($field->getEntityTypeId())->resetCache([$field->id()]);
+      $field = FieldConfig::loadByName($this->entityType, $this->bundle, $this->fieldName);
       $this->assertConfigEntityImport($field);
 
       // Once the default value has been removed after saving the dependency
diff --git a/core/modules/field/src/Entity/FieldConfig.php b/core/modules/field/src/Entity/FieldConfig.php
index c5b9ad5..802bc1b 100644
--- a/core/modules/field/src/Entity/FieldConfig.php
+++ b/core/modules/field/src/Entity/FieldConfig.php
@@ -182,6 +182,7 @@ public function calculateDependencies() {
   public static function preDelete(EntityStorageInterface $storage, array $fields) {
     $state = \Drupal::state();
 
+    parent::preDelete($storage, $fields);
     // Keep the field definitions in the state storage so we can use them
     // later during field_purge_batch().
     $deleted_fields = $state->get('field.field.deleted') ?: array();
@@ -222,7 +223,7 @@ public static function postDelete(EntityStorageInterface $storage, array $fields
     $storages_to_delete = array();
     foreach ($fields as $field) {
       $storage_definition = $field->getFieldStorageDefinition();
-      if (!$field->deleted && empty($field->noFieldDelete) && !$field->isUninstalling() && $storage_definition->isDeletable()) {
+      if (!$field->deleted && !$field->isUninstalling() && $storage_definition->isDeletable()) {
         // Key by field UUID to avoid deleting the same storage twice.
         $storages_to_delete[$storage_definition->uuid()] = $storage_definition;
       }
@@ -230,29 +231,6 @@ public static function postDelete(EntityStorageInterface $storage, array $fields
     if ($storages_to_delete) {
       \Drupal::entityManager()->getStorage('field_storage_config')->delete($storages_to_delete);
     }
-
-    // Cleanup entity displays.
-    $displays_to_update = array();
-    foreach ($fields as $field) {
-      if (!$field->deleted) {
-        $view_modes = \Drupal::entityManager()->getViewModeOptions($field->entity_type, TRUE);
-        foreach (array_keys($view_modes) as $mode) {
-          $displays_to_update['entity_view_display'][$field->entity_type . '.' . $field->bundle . '.' . $mode][] = $field->getName();
-        }
-        $form_modes = \Drupal::entityManager()->getFormModeOptions($field->entity_type, TRUE);
-        foreach (array_keys($form_modes) as $mode) {
-          $displays_to_update['entity_form_display'][$field->entity_type . '.' . $field->bundle . '.' . $mode][] = $field->getName();
-        }
-      }
-    }
-    foreach ($displays_to_update as $type => $ids) {
-      foreach (entity_load_multiple($type, array_keys($ids)) as $id => $display) {
-        foreach ($ids[$id] as $field_name) {
-          $display->removeComponent($field_name);
-        }
-        $display->save();
-      }
-    }
   }
 
   /**
diff --git a/core/modules/field/src/Entity/FieldStorageConfig.php b/core/modules/field/src/Entity/FieldStorageConfig.php
index ab869db..a1c2d58 100644
--- a/core/modules/field/src/Entity/FieldStorageConfig.php
+++ b/core/modules/field/src/Entity/FieldStorageConfig.php
@@ -198,6 +198,13 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
   protected $propertyDefinitions;
 
   /**
+   * Static flag set to prevent recursion during field deletes.
+   *
+   * @var bool
+   */
+  protected static $inDeletion = FALSE;
+
+  /**
    * Constructs a FieldStorageConfig object.
    *
    * @param array $values
@@ -374,29 +381,13 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
    */
   public static function preDelete(EntityStorageInterface $storage, array $field_storages) {
     $state = \Drupal::state();
-    $field_config_storage = \Drupal::entityManager()->getStorage('field_config');
 
-    // Delete fields first. Note: when deleting a field storage through
-    // FieldConfig::postDelete(), the fields have been deleted already, so
-    // no fields will be found here.
-    $field_ids = array();
-    foreach ($field_storages as $field_storage) {
-      if (!$field_storage->deleted) {
-        foreach ($field_storage->getBundles() as $bundle) {
-          $entity_type = $field_storage->getTargetEntityTypeId();
-          $field_name = $field_storage->getName();
-          $field_ids[] = "{$entity_type}.$bundle.{$field_name}";
-        }
-      }
-    }
-    if ($field_ids) {
-      $fields = $field_config_storage->loadMultiple($field_ids);
-      // Tag the objects to preserve recursive deletion of the field.
-      foreach ($fields as $field) {
-        $field->noFieldDelete = TRUE;
-      }
-      $field_config_storage->delete($fields);
-    }
+    // Set the static flag so that we don't delete field storages whilst
+    // deleting fields.
+    static::$inDeletion = TRUE;
+
+    // Delete or fix any configuration that is dependent, for example, fields.
+    parent::preDelete($storage, $field_storages);
 
     // Keep the field definitions in the state storage so we can use them later
     // during field_purge_batch().
@@ -424,6 +415,8 @@ public static function postDelete(EntityStorageInterface $storage, array $fields
         $field->deleted = TRUE;
       }
     }
+    // Unset static flag.
+    static::$inDeletion = FALSE;
   }
 
   /**
@@ -794,8 +787,9 @@ public static function loadByName($entity_type_id, $field_name) {
    */
   public function isDeletable() {
     // The field storage is not deleted, is configured to be removed when there
-    // are no fields and the field storage has no bundles.
-    return !$this->deleted && !$this->persist_with_no_fields && count($this->getBundles()) == 0;
+    // are no fields, the field storage has no bundles, and field storages are
+    // not in the process of being deleted.
+    return !$this->deleted && !$this->persist_with_no_fields && count($this->getBundles()) == 0 && !static::$inDeletion;
   }
 
   /**
diff --git a/core/modules/system/src/Form/ModulesUninstallConfirmForm.php b/core/modules/system/src/Form/ModulesUninstallConfirmForm.php
index d6e5b15..159959d 100644
--- a/core/modules/system/src/Form/ModulesUninstallConfirmForm.php
+++ b/core/modules/system/src/Form/ModulesUninstallConfirmForm.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Form;
 
 use Drupal\Core\Config\ConfigManagerInterface;
+use Drupal\Core\Config\Entity\ConfigDependencyDeleteFormTrait;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
@@ -21,6 +22,7 @@
  * Builds a confirmation form to uninstall selected modules.
  */
 class ModulesUninstallConfirmForm extends ConfirmFormBase {
+  use ConfigDependencyDeleteFormTrait;
 
   /**
    * The module installer service.
@@ -145,86 +147,8 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       }, $this->modules),
     );
 
-    // Get the dependent entities.
-    $entity_types = array();
-    $dependent_entities = $this->configManager->getConfigEntitiesToChangeOnDependencyRemoval('module', $this->modules);
-
-    $form['entity_updates'] = array(
-      '#type' => 'details',
-      '#title' => $this->t('Configuration updates'),
-      '#description' => $this->t('The listed configuration will be updated.'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-      '#access' => FALSE,
-    );
-
-    foreach ($dependent_entities['update'] as $entity) {
-      /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface  $entity */
-      $entity_type_id = $entity->getEntityTypeId();
-      if (!isset($form['entity_updates'][$entity_type_id])) {
-        $entity_type = $this->entityManager->getDefinition($entity_type_id);
-        // Store the ID and label to sort the entity types and entities later.
-        $label = $entity_type->getLabel();
-        $entity_types[$entity_type_id] = $label;
-        $form['entity_updates'][$entity_type_id] = array(
-          '#theme' => 'item_list',
-          '#title' => $label,
-          '#items' => array(),
-        );
-      }
-      $form['entity_updates'][$entity_type_id]['#items'][] = $entity->label() ?: $entity->id();
-    }
-    if (!empty($dependent_entities['update'])) {
-      $form['entity_updates']['#access'] = TRUE;
-
-      // Add a weight key to the entity type sections.
-      asort($entity_types, SORT_FLAG_CASE);
-      $weight = 0;
-      foreach ($entity_types as $entity_type_id => $label) {
-        $form['entity_updates'][$entity_type_id]['#weight'] = $weight;
-        // Sort the list of entity labels alphabetically.
-        sort($form['entity_updates'][$entity_type_id]['#items'], SORT_FLAG_CASE);
-        $weight++;
-      }
-    }
-
-    $form['entity_deletes'] = array(
-      '#type' => 'details',
-      '#title' => $this->t('Configuration deletions'),
-      '#description' => $this->t('The listed configuration will be deleted.'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-      '#access' => FALSE,
-    );
-
-    foreach ($dependent_entities['delete'] as $entity) {
-      $entity_type_id = $entity->getEntityTypeId();
-      if (!isset($form['entity_deletes'][$entity_type_id])) {
-        $entity_type = $this->entityManager->getDefinition($entity_type_id);
-        // Store the ID and label to sort the entity types and entities later.
-        $label = $entity_type->getLabel();
-        $entity_types[$entity_type_id] = $label;
-        $form['entity_deletes'][$entity_type_id] = array(
-          '#theme' => 'item_list',
-          '#title' => $label,
-          '#items' => array(),
-        );
-      }
-      $form['entity_deletes'][$entity_type_id]['#items'][] = $entity->label() ?: $entity->id();
-    }
-    if (!empty($dependent_entities['delete'])) {
-      $form['entity_deletes']['#access'] = TRUE;
-
-      // Add a weight key to the entity type sections.
-      asort($entity_types, SORT_FLAG_CASE);
-      $weight = 0;
-      foreach ($entity_types as $entity_type_id => $label) {
-        $form['entity_deletes'][$entity_type_id]['#weight'] = $weight;
-        // Sort the list of entity labels alphabetically.
-        sort($form['entity_deletes'][$entity_type_id]['#items'], SORT_FLAG_CASE);
-        $weight++;
-      }
-    }
+    // List the dependent entities.
+    $this->addDependencyListsToForm($form, 'module', $this->modules ,$this->configManager, $this->entityManager);
 
     return parent::buildForm($form, $form_state);
   }
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
index 4ed1c20..9f05892 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
@@ -97,6 +97,13 @@ class ConfigEntityStorageTest extends UnitTestCase {
   protected $typedConfigManager;
 
   /**
+   * The configuration manager.
+   *
+   * @var \Drupal\Core\Config\ConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $configManager;
+
+  /**
    * {@inheritdoc}
    *
    * @covers ::__construct
@@ -160,10 +167,14 @@ protected function setUp() {
     $this->typedConfigManager->expects($this->any())
       ->method('getDefinition')
       ->will($this->returnValue(array('mapping' => array('id' => '', 'uuid' => '', 'dependencies' => ''))));
+
+    $this->configManager = $this->getMock('Drupal\Core\Config\ConfigManagerInterface');
+
     $container = new ContainerBuilder();
     $container->set('entity.manager', $this->entityManager);
     $container->set('config.typed', $this->typedConfigManager);
     $container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
+    $container->set('config.manager', $this->configManager);
     \Drupal::setContainer($container);
 
   }
@@ -728,6 +739,11 @@ public function testDeleteRevision() {
    * @covers ::doDelete
    */
   public function testDelete() {
+    // Dependencies are tested elsewhere.
+    // @see \Drupal\config\Tests\ConfigDependencyTest
+    $this->configManager->expects($this->any())
+      ->method('getConfigEntitiesToChangeOnDependencyRemoval')
+      ->willReturn(['update' => [], 'delete' => [], 'unchanged' => []]);
     $entities = array();
     $configs = array();
     $config_map = array();
