diff --git a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
index 79b9292..3f28a78 100644
--- a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
@@ -120,6 +120,13 @@
   protected $renderer;
 
   /**
+   * The 'system' channel logger service.
+   *
+   * @var \Psr\Log\LoggerInterface
+   */
+  protected $logger;
+
+  /**
    * {@inheritdoc}
    */
   public function __construct(array $values, $entity_type) {
@@ -132,6 +139,7 @@ public function __construct(array $values, $entity_type) {
     }
 
     $this->renderer = \Drupal::service('renderer');
+    $this->logger = \Drupal::logger('system');
 
     // A plugin manager and a context type needs to be set by extending classes.
     if (!isset($this->pluginManager)) {
@@ -428,19 +436,88 @@ public function onDependencyRemoval(array $dependencies) {
       }
     }
     foreach ($this->getComponents() as $name => $component) {
-      if (isset($component['type']) && $definition = $this->pluginManager->getDefinition($component['type'], FALSE)) {
-        if (in_array($definition['provider'], $dependencies['module'])) {
+      if ($renderer = $this->getRenderer($name)) {
+        if (in_array($renderer->getPluginDefinition()['provider'], $dependencies['module'])) {
           // Revert to the defaults if the plugin that supplies the widget or
           // formatter depends on a module that is being uninstalled.
           $this->setComponent($name);
           $changed = TRUE;
         }
+
+        // Give this component the opportunity to react on dependency removal.
+        $component_removed_dependencies = $this->getPluginRemovedDependencies($renderer->calculateDependencies(), $dependencies);
+        if ($component_removed_dependencies) {
+          if ($renderer->onDependencyRemoval($component_removed_dependencies)) {
+            // Update component settings to reflect changes.
+            $component['settings'] = $renderer->getSettings();
+            $component['third_party_settings'] = [];
+            foreach ($renderer->getThirdPartyProviders() as $module) {
+              $component['third_party_settings'][$module] = $renderer->getThirdPartySettings($module);
+            }
+            $this->setComponent($name, $component);
+            $changed = TRUE;
+          }
+          // If there are unresolved deleted dependencies left, disable this
+          // component to avoid the removal of the entire display entity.
+          if ($this->getPluginRemovedDependencies($renderer->calculateDependencies(), $dependencies)) {
+            $this->removeComponent($name);
+            $arguments = [
+              '@display' => (string) $this->getEntityType()->getLabel(),
+              '@id' => $this->id(),
+              '@name' => $name,
+            ];
+            $this->logger->warning("@display '@id': Component '@name' was disabled because its settings depend on removed dependencies.", $arguments);
+            $changed = TRUE;
+          }
+        }
       }
     }
     return $changed;
   }
 
   /**
+   * Returns the plugin dependencies being removed.
+   *
+   * The function recursively computes the intersection between all plugin
+   * dependencies and all removed dependencies.
+   *
+   * Note: The two arguments do not have the same structure.
+   *
+   * @param array[] $plugin_dependencies
+   *   A list of dependencies having the same structure as the return value of
+   *   ConfigEntityInterface::calculateDependencies().
+   * @param array[] $removed_dependencies
+   *   A list of dependencies having the same structure as the input argument of
+   *   ConfigEntityInterface::onDependencyRemoval().
+   *
+   * @return array
+   *   A recursively computed intersection.
+   *
+   * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies()
+   * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval()
+   */
+  protected function getPluginRemovedDependencies(array $plugin_dependencies, array $removed_dependencies) {
+    $intersect = [];
+    foreach ($plugin_dependencies as $type => $dependencies) {
+      if ($removed_dependencies[$type]) {
+        // Config and content entities have the dependency names as keys while
+        // module and theme dependencies are indexed arrays of dependency names.
+        // @see \Drupal\Core\Config\ConfigManager::callOnDependencyRemoval()
+        if (in_array($type, ['config', 'content'])) {
+          $removed = array_intersect_key($removed_dependencies[$type], array_flip($dependencies));
+        }
+        else {
+          $removed = array_values(array_intersect($removed_dependencies[$type], $dependencies));
+        }
+        if ($removed) {
+          $intersect[$type] = $removed;
+        }
+      }
+    }
+    return $intersect;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function __sleep() {
diff --git a/core/lib/Drupal/Core/Field/PluginSettingsBase.php b/core/lib/Drupal/Core/Field/PluginSettingsBase.php
index 1baf31d..c61d96f 100644
--- a/core/lib/Drupal/Core/Field/PluginSettingsBase.php
+++ b/core/lib/Drupal/Core/Field/PluginSettingsBase.php
@@ -97,6 +97,16 @@ public function setSetting($key, $value) {
   /**
    * {@inheritdoc}
    */
+  public function getThirdPartySettings($module = NULL) {
+    if ($module) {
+      return isset($this->thirdPartySettings[$module]) ? $this->thirdPartySettings[$module] : NULL;
+    }
+    return $this->thirdPartySettings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getThirdPartySetting($module, $key, $default = NULL) {
     return isset($this->thirdPartySettings[$module][$key]) ? $this->thirdPartySettings[$module][$key] : $default;
   }
@@ -112,6 +122,26 @@ public function setThirdPartySetting($module, $key, $value) {
   /**
    * {@inheritdoc}
    */
+  public function unsetThirdPartySetting($module, $key) {
+    unset($this->thirdPartySettings[$module][$key]);
+    // If the third party is no longer storing any information, completely
+    // remove the array holding the settings for this module.
+    if (empty($this->thirdPartySettings[$module])) {
+      unset($this->thirdPartySettings[$module]);
+    }
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getThirdPartyProviders() {
+    return array_keys($this->thirdPartySettings);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function calculateDependencies() {
     if (!empty($this->thirdPartySettings)) {
       // Create dependencies on any modules providing third party settings.
@@ -122,4 +152,17 @@ public function calculateDependencies() {
     return array();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function onDependencyRemoval(array $dependencies) {
+    $changed = FALSE;
+    if (!empty($this->thirdPartySettings) && !empty($dependencies['module'])) {
+      $old_count = count($this->thirdPartySettings);
+      $this->thirdPartySettings = array_diff_key($this->thirdPartySettings, array_flip($dependencies['module']));
+      $changed = $old_count != count($this->thirdPartySettings);
+    }
+    return $changed;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Field/PluginSettingsInterface.php b/core/lib/Drupal/Core/Field/PluginSettingsInterface.php
index 969061f..8ee2ac5 100644
--- a/core/lib/Drupal/Core/Field/PluginSettingsInterface.php
+++ b/core/lib/Drupal/Core/Field/PluginSettingsInterface.php
@@ -8,11 +8,12 @@
 namespace Drupal\Core\Field;
 
 use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Core\Config\Entity\ThirdPartySettingsInterface;
 
 /**
  * Interface definition for plugin with settings.
  */
-interface PluginSettingsInterface extends PluginInspectionInterface {
+interface PluginSettingsInterface extends PluginInspectionInterface, ThirdPartySettingsInterface {
 
   /**
    * Defines the default settings for this plugin.
@@ -65,34 +66,27 @@ public function setSettings(array $settings);
   public function setSetting($key, $value);
 
   /**
-   * Returns the value of a third-party setting, or $default if not set.
+   * Informs the plugin that some configuration it depends on will be deleted.
    *
-   * @param string $module
-   *   The module providing the third-party setting.
-   * @param string $key
-   *   The setting name.
-   * @param mixed $default
-   *   (optional) The default value if the third party setting is not set.
-   *   Defaults to NULL.
+   * This method allows plugins to keep their configuration up-to-date when a
+   * dependency calculated with ::calculateDependencies() is removed. For
+   * example, an entity view display contains a formatter having a setting
+   * pointing to an arbitrary config entity. When that config entity is deleted,
+   * this method is called by the view display to react to the dependency
+   * removal by updating its configuration.
    *
-   * @return mixed|NULL
-   *   The setting value. Returns NULL if the setting does not exist and
-   *   $default is not provided.
-   */
-  public function getThirdPartySetting($module, $key, $default = NULL);
-
-  /**
-   * Sets the value of a third-party setting for the plugin.
+   * This method must return TRUE if the removal event updated the plugin
+   * configuration or FALSE otherwise.
    *
-   * @param string $module
-   *   The module providing the third-party setting.
-   * @param string $key
-   *   The setting name.
-   * @param mixed $value
-   *   The setting value.
+   * @param array $dependencies
+   *   An array of dependencies that will be deleted keyed by dependency type.
+   *   Dependency types are 'config', 'content', 'module' and 'theme'.
    *
-   * @return $this
+   * @return bool
+   *   TRUE if the plugin configuration has changed, FALSE if not.
+   *
+   * @see \Drupal\Core\Entity\EntityDisplayBase
    */
-  public function setThirdPartySetting($module, $key, $value);
+  public function onDependencyRemoval(array $dependencies);
 
 }
diff --git a/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml b/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml
index 8e06db1..3712b47 100644
--- a/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml
+++ b/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml
@@ -40,6 +40,12 @@ field.widget.settings.test_field_widget:
     test_widget_setting:
       type: string
       label: 'Test setting'
+    role:
+      type: string
+      label: 'A referenced role'
+    role2:
+      type: string
+      label: 'A 2nd referenced role'
 
 field.widget.settings.test_field_widget_multiple:
   type: mapping
@@ -49,6 +55,14 @@ field.widget.settings.test_field_widget_multiple:
       type: string
       label: 'Test setting'
 
+field.widget.third_party.color:
+  type: mapping
+  label: 'Field test entity display color module third party settings'
+  mapping:
+    foo:
+      type: string
+      label: 'Foo setting'
+
 field.storage_settings.test_field:
   type: mapping
   label: 'Test field storage settings'
diff --git a/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldWidget/TestFieldWidget.php b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldWidget/TestFieldWidget.php
index b90008a..a68e235 100644
--- a/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldWidget/TestFieldWidget.php
+++ b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldWidget/TestFieldWidget.php
@@ -34,6 +34,8 @@ class TestFieldWidget extends WidgetBase {
   public static function defaultSettings() {
     return array(
       'test_widget_setting' => 'dummy test string',
+      'role' => 'anonymous',
+      'role2' => 'anonymous',
     ) + parent::defaultSettings();
   }
 
@@ -78,4 +80,42 @@ public function errorElement(array $element, ConstraintViolationInterface $viola
     return $element['value'];
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    $dependencies = parent::calculateDependencies();
+
+    foreach (['role', 'role2'] as $setting) {
+      if (!empty($role_id = $this->getSetting($setting))) {
+        // Create a dependency on the role config entity referenced in settings.
+        $dependencies['config'][] = "user.role.$role_id";
+      }
+    }
+
+    return $dependencies;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function onDependencyRemoval(array $dependencies) {
+    $changed = parent::onDependencyRemoval($dependencies);
+
+    // Only the setting 'role' is resolved here. When the dependency related to
+    // this setting is removed, is expected that the widget component will be
+    // update accordingly in the display entity. The 'role2' setting is
+    // deliberately left out from being updated. When the dependency
+    // corresponding to this setting is removed, is expected that the widget
+    // component will be disabled in the display entity.
+    if (!empty($role_id = $this->getSetting('role'))) {
+      if (!empty($dependencies['config']["user.role.$role_id"])) {
+        $this->setSetting('role', 'anonymous');
+        $changed = TRUE;
+      }
+    }
+
+    return $changed;
+  }
+
 }
diff --git a/core/modules/field_ui/src/Tests/EntityDisplayTest.php b/core/modules/field_ui/src/Tests/EntityDisplayTest.php
index 53a8639..13eb95b 100644
--- a/core/modules/field_ui/src/Tests/EntityDisplayTest.php
+++ b/core/modules/field_ui/src/Tests/EntityDisplayTest.php
@@ -7,7 +7,11 @@
 
 namespace Drupal\field_ui\Tests;
 
+use Drupal\Component\Utility\FormattableString;
+use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Database\Database;
+use Drupal\Core\Entity\Display\EntityDisplayInterface;
 use Drupal\Core\Entity\Entity\EntityFormDisplay;
 use Drupal\Core\Entity\Entity\EntityViewDisplay;
 use Drupal\Core\Entity\Entity\EntityViewMode;
@@ -15,7 +19,7 @@
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\node\Entity\NodeType;
 use Drupal\simpletest\KernelTestBase;
-use Drupal\Tests\Core\Entity\EntityManagerTest;
+use Drupal\user\Entity\Role;
 
 /**
  * Tests the entity display configuration entities.
@@ -503,4 +507,171 @@ public function testGetDisplayModeOptions() {
     $this->assertEqual($form_modes, array('default' => 'Default', 'register' => 'Register'));
   }
 
+  /**
+   * Tests components dependencies additions.
+   */
+  public function testComponentDependencies() {
+    $this->enableModules(['dblog', 'color']);
+    $this->installSchema('dblog', ['watchdog']);
+    $this->installEntitySchema('user');
+    /** @var \Drupal\user\RoleInterface[] $roles */
+    $roles = [];
+    // Create two arbitrary user roles.
+    for ($i = 0; $i < 2; $i++) {
+      $roles[$i] = Role::create([
+        'id' => Unicode::strtolower($this->randomMachineName()),
+        'label' => $this->randomString(),
+      ]);
+      $roles[$i]->save();
+    }
+
+    // Create a field of type 'test_field' attached to 'entity_test'.
+    $field_name = Unicode::strtolower($this->randomMachineName());
+    FieldStorageConfig::create([
+      'field_name' => $field_name,
+      'entity_type' => 'entity_test',
+      'type' => 'test_field',
+    ])->save();
+    FieldConfig::create([
+      'field_name' => $field_name,
+      'entity_type' => 'entity_test',
+      'bundle' => 'entity_test',
+    ])->save();
+
+    // Create a new form display without components.
+    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
+    $form_display = EntityFormDisplay::create([
+      'targetEntityType' => 'entity_test',
+      'bundle' => 'entity_test',
+      'mode' => 'default',
+    ]);
+    $form_display->save();
+
+    $dependencies = ['user.role.' . $roles[0]->id(), 'user.role.' . $roles[1]->id()];
+
+    // The config object should not depend on none of the two $roles.
+    $this->assertNoDependency('config', $dependencies[0], $form_display);
+    $this->assertNoDependency('config', $dependencies[1], $form_display);
+
+    // Add a widget of type 'test_field_widget'.
+    $component = [
+      'type' => 'test_field_widget',
+      'settings' => [
+        'test_widget_setting' => $this->randomString(),
+        'role' => $roles[0]->id(),
+        'role2' => $roles[1]->id(),
+      ],
+      'third_party_settings' => [
+        'color' => ['foo' => 'bar'],
+      ],
+    ];
+    $form_display->setComponent($field_name, $component);
+    $form_display->save();
+
+    // Now, the form display should depend on both user roles $roles.
+    $this->assertDependency('config', $dependencies[0], $form_display);
+    $this->assertDependency('config', $dependencies[1], $form_display);
+    // The form display should depend on 'color' module.
+    $this->assertDependency('module', 'color', $form_display);
+
+    // Delete the first user role entity.
+    $roles[0]->delete();
+
+    // Reload the form display.
+    $form_display = EntityFormDisplay::load($form_display->id());
+    // The display exists.
+    $this->assertFalse(empty($form_display));
+    // The form display should not depend on $role[0] anymore.
+    $this->assertNoDependency('config', $dependencies[0], $form_display);
+    // The form display should depend on 'anonymous' user role.
+    $this->assertDependency('config', 'user.role.anonymous', $form_display);
+    // The form display should depend on 'color' module.
+    $this->assertDependency('module', 'color', $form_display);
+
+    // Manually trigger the removal of configuration belonging to the module
+    // because KernelTestBase::disableModules() is not aware of this.
+    $this->container->get('config.manager')->uninstall('module', 'color');
+    // Uninstall 'color' module.
+    $this->disableModules(['color']);
+
+    // Reload the form display.
+    $form_display = EntityFormDisplay::load($form_display->id());
+    // The display exists.
+    $this->assertFalse(empty($form_display));
+    // The component is still enabled.
+    $this->assertNotNull($form_display->getComponent($field_name));
+    // The form display should not depend on 'color' module anymore.
+    $this->assertNoDependency('module', 'color', $form_display);
+
+    // Delete the 2nd user role entity.
+    $roles[1]->delete();
+
+    // Reload the form display.
+    $form_display = EntityFormDisplay::load($form_display->id());
+    // The display exists.
+    $this->assertFalse(empty($form_display));
+    // The component has been disabled.
+    $this->assertNull($form_display->getComponent($field_name));
+    $this->assertTrue($form_display->get('hidden')[$field_name]);
+    // The correct warning message has been logged.
+    $arguments = ['@display' => (string) t('Entity form display'), '@id' => $form_display->id(), '@name' => $field_name];
+    $logged = (bool) Database::getConnection()->select('watchdog', 'w')
+      ->fields('w', ['wid'])
+      ->condition('type', 'system')
+      ->condition('message', "@display '@id': Component '@name' was disabled because its settings depend on removed dependencies.")
+      ->condition('variables', serialize($arguments))
+      ->execute()
+      ->fetchAll();
+    $this->assertTrue($logged);
+  }
+
+  /**
+   * Asserts that $key is a $type type dependency of $display config entity.
+   *
+   * @param string $type
+   *   The dependency type: 'config', 'content', 'module' or 'theme'.
+   * @param string $key
+   *   The string to be checked.
+   * @param \Drupal\Core\Entity\Display\EntityDisplayInterface $display
+   *   The entity display object to get dependencies from.
+   */
+  protected function assertDependency($type, $key, EntityDisplayInterface $display) {
+    $this->assertDependencyHelper(TRUE, $type, $key, $display);
+  }
+
+  /**
+   * Asserts that $key is not a $type type dependency of $display config entity.
+   *
+   * @param string $type
+   *   The dependency type: 'config', 'content', 'module' or 'theme'.
+   * @param string $key
+   *   The string to be checked.
+   * @param \Drupal\Core\Entity\Display\EntityDisplayInterface $display
+   *   The entity display object to get dependencies from.
+   */
+  protected function assertNoDependency($type, $key, EntityDisplayInterface $display) {
+    $this->assertDependencyHelper(FALSE, $type, $key, $display);
+  }
+
+  /**
+   * Provides a helper for dependency assertions.
+   *
+   * @param bool $assertion
+   *   Assertion: positive or negative.
+   * @param string $type
+   *   The dependency type: 'config', 'content', 'module' or 'theme'.
+   * @param string $key
+   *   The string to be checked.
+   * @param \Drupal\Core\Entity\Display\EntityDisplayInterface $display
+   *   The entity display object to get dependencies from.
+   */
+  protected function assertDependencyHelper($assertion, $type, $key, EntityDisplayInterface $display) {
+    $all_dependencies = $display->getDependencies();
+    $dependencies = !empty($all_dependencies[$type]) ? $all_dependencies[$type] : [];
+    $value = $assertion ? in_array($key, $dependencies) : !in_array($key, $dependencies);
+    $args = ['@value' => var_export($value, TRUE)];
+    $message = $assertion ? new FormattableString('Value @value is TRUE.', $args) : new FormattableString('Value @value is FALSE.', $args);
+    $this->assert($value, $message);
+  }
+
 }
