diff --git a/config/schema/field_formatter.schema.yml b/config/schema/field_formatter.schema.yml
index ca8d04e..122179b 100644
--- a/config/schema/field_formatter.schema.yml
+++ b/config/schema/field_formatter.schema.yml
@@ -24,6 +24,20 @@ field.formatter.settings.field_formatter_with_inline_settings:
       label: 'Target field label visibility setting'
       type: string
 
+field.formatter.settings.field_formatter__per_bundle:
+  type: ignore
+#  type: mapping
+#  mapping:
+#    formatter:
+#      type: sequence
+#      sequence:
+#        type: mapping
+#        mapping:
+#          type:
+#            type: string
+#          settings:
+#            type: any
+
 field.formatter.settings.field_link:
   type: mapping
   mapping:
diff --git a/src/Plugin/Field/FieldFormatter/FieldFormatterPerBundle.php b/src/Plugin/Field/FieldFormatter/FieldFormatterPerBundle.php
new file mode 100644
index 0000000..3bec261
--- /dev/null
+++ b/src/Plugin/Field/FieldFormatter/FieldFormatterPerBundle.php
@@ -0,0 +1,347 @@
+<?php
+
+namespace Drupal\field_formatter\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Entity\Entity\EntityViewDisplay;
+use Drupal\Core\Field\BaseFieldDefinition;
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Field\FormatterInterface;
+use Drupal\Core\Field\FormatterPluginManager;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Formatter for ER fields that allows to choose formatters per bundle.
+ *
+ * @FieldFormatter(
+ *   id = "field_formatter__per_bundle",
+ *   label = @Translation("Formatter per bundle"),
+ *   field_types = {
+ *     "entity_reference",
+ *     "entity_reference_revisions",
+ *   },
+ * )
+ */
+class FieldFormatterPerBundle extends FieldFormatterBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The formatter plugin manager.
+   *
+   * @var \Drupal\Core\Field\FormatterPluginManager
+   */
+  protected $formatterPluginManager;
+
+  /**
+   * Constructs a FieldFormatterWithInlineSettings object.
+   *
+   * @param string $plugin_id
+   *   The plugin_id for the formatter.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   The definition of the field to which the formatter is associated.
+   * @param array $settings
+   *   The formatter settings.
+   * @param string $label
+   *   The formatter label display setting.
+   * @param string $view_mode
+   *   The view mode.
+   * @param array $third_party_settings
+   *   Any third party settings.
+   * @param \Drupal\Core\Field\FormatterPluginManager $formatter_plugin_manager
+   *   The formatter plugin manager.
+   */
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, FormatterPluginManager $formatter_plugin_manager) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
+    $this->formatterPluginManager = $formatter_plugin_manager;
+  }
+
+  /**
+   * {@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['label'],
+      $configuration['view_mode'],
+      $configuration['third_party_settings'],
+      $container->get('plugin.manager.field.formatter')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return [
+      'formatter' => [],
+    ] + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items, $langcode) {
+    /** @var \Drupal\Core\Entity\FieldableEntityInterface $entity */
+    $entities = $this->getEntitiesToView($items, $langcode);
+    $parent_entity = $items->getEntity();
+
+    $build = [];
+    foreach ($entities as $delta => $entity) {
+      /** @var \Drupal\Core\Entity\FieldableEntityInterface $fake_entity */
+      $fake_entity = clone $parent_entity;
+      $fake_entity->get($items->getName())->setValue([
+        $entity,
+      ]);
+
+      $build[$delta] = $this->getViewDisplay($entity->bundle())->build($fake_entity);
+    }
+    return $build;
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getViewDisplay($bundle_id) {
+    if (!isset($this->viewDisplay[$bundle_id])) {
+
+      $display = EntityViewDisplay::create([
+        'targetEntityType' => $this->fieldDefinition->getTargetEntityTypeId(),
+        'bundle' => $this->fieldDefinition->getTargetBundle(),
+        'status' => TRUE,
+      ]);
+      if ($bundle_settings = $this->getBundleSettings($bundle_id)) {
+        $display->setComponent($this->fieldDefinition->getName(), [
+          'type' => $bundle_settings['type'],
+          'settings' => $bundle_settings['settings'],
+        ]);
+      }
+      $this->viewDisplay[$bundle_id] = $display;
+    }
+    return $this->viewDisplay[$bundle_id];
+  }
+
+  /**
+   * Returns the formatter settings for a specific bundle.
+   *
+   * @param string $bundle_id
+   *   The bundle ID.
+   *
+   * @return array
+   *   - type: The formatter type
+   *   - settings: The formatter settings
+   */
+  protected function getBundleSettings($bundle_id) {
+    $settings = $this->getSetting('formatter');
+    $settings[$bundle_id] += [
+      'settings' => [],
+    ];
+    if (isset($settings[$bundle_id])) {
+      return $settings[$bundle_id];
+    }
+    return [];
+  }
+
+
+  /**
+   * Ajax submit callback for formatter type change.
+   *
+   * @param array $form
+   *   The form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   *
+   * @return array
+   *   The replaced form substructure.
+   */
+  public static function onFormatterTypeChange(array $form, FormStateInterface $form_state) {
+    $bundle = static::getChangedFieldAndBundle($form_state);
+
+    return $form['fields'][$form_state->getStorage()['plugin_settings_edit']]['plugin']['settings_edit_form']['settings']['formatter'][$bundle]['settings'];
+  }
+
+  protected static function getChangedFieldAndBundle(FormStateInterface $form_state) {
+    // Determine on which bundle this change was.
+    // We look at the #name of the submitted formatter. In case there are better
+    // ways, please let us know.
+    $name = $form_state->getTriggeringElement()['#name'];
+    $name = str_replace('fields[' . $form_state->getStorage()['plugin_settings_edit'] . '][settings_edit_form][settings][formatter][', '', $name);
+    $bundle = str_replace('][type]', '', $name);
+    return $bundle;
+  }
+
+  /**
+   * Rebuilds the form on select submit.
+   *
+   * @param array $form
+   *   The form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   */
+  public static function rebuildSubmit(array $form, FormStateInterface $form_state) {
+    $form_state->setRebuild(TRUE);
+
+    // Clear the settings as the formatter type changed.
+    $bundle = static::getChangedFieldAndBundle($form_state);
+    $form_state->setValue([
+      'fields',
+      $form_state->getStorage()['plugin_settings_edit'],
+      'settings_edit_form',
+      'settings',
+      'formatter',
+      $bundle,
+      'settings'
+    ], []);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $form = parent::settingsForm($form, $form_state);
+
+    $field_storage = $this->fieldDefinition->getFieldStorageDefinition();
+
+    $form['#prefix'] = '<div id="field-formatter-ajax">';
+    $form['#suffix'] = '</div>';
+
+    $formatter_options = $this->getAvailableFormatterOptions($field_storage);
+
+    $handler_settings = $this->fieldDefinition->getSetting('handler_settings');
+    if (empty($handler_settings['target_bundles'])) {
+      return $form;
+    }
+
+    foreach ($handler_settings['target_bundles'] as $bundle) {
+      $formatter_type = $this->getSettingFromFormState($form_state, $bundle, 'type');
+      $settings = $this->getSettingFromFormState($form_state, $bundle, 'settings') ?: [];
+      if (!isset($formatter_options[$formatter_type])) {
+        $formatter_type = key($formatter_options);
+        $settings = [];
+      }
+
+      $form['formatter'][$bundle]['label'] = [
+        '#markup' => '<h4>' . $bundle . '</h4>',
+      ];
+      $form['formatter'][$bundle]['type'] = [
+        '#type' => 'select',
+        '#title' => $this->t('Formatter'),
+        '#options' => $formatter_options,
+        '#default_value' => $formatter_type,
+        // Note: We cannot use ::foo syntax, because the form is the entity form
+        // display.
+        '#ajax' => [
+          'callback' => [get_called_class(), 'onFormatterTypeChange'],
+          'wrapper' => 'field-formatter-settings-ajax-' . $bundle,
+          'method' => 'replace',
+        ],
+        '#submit' => [[get_called_class(), 'rebuildSubmit']],
+        '#executes_submit_callback' => TRUE,
+      ];
+
+      $options = [
+        'field_definition' => $this->getFieldDefinition($field_storage),
+        'configuration' => [
+          'type' => $formatter_type,
+          'settings' => $settings,
+          'label' => '',
+          'weight' => 0,
+        ],
+        'view_mode' => '_custom',
+      ];
+
+      // Get the formatter settings form.
+      $settings_form = ['#value' => []];
+      if ($formatter = $this->formatterPluginManager->getInstance($options)) {
+        $settings_form = $formatter->settingsForm([], $form_state);
+      }
+      $form['formatter'][$bundle]['settings'] = $settings_form;
+      $form['formatter'][$bundle]['settings']['#prefix'] = '<div id="field-formatter-settings-ajax-' . $bundle . '">';
+      $form['formatter'][$bundle]['settings']['#suffix'] = '</div>';
+    }
+
+    return $form;
+  }
+
+  protected function getSettingFromFormState(FormStateInterface $form_state, $bundle, $setting) {
+    $field_name = $this->fieldDefinition->getName();
+    if ($form_state->hasValue(['fields', $field_name, 'settings_edit_form', 'settings', 'formatter', $bundle, $setting])) {
+      return $form_state->getValue(['fields', $field_name, 'settings_edit_form', 'settings', 'formatter', $bundle, $setting]);
+    }
+
+    if (isset($this->settings['formatter'][$bundle][$setting])) {
+      return $this->settings['formatter'][$bundle][$setting];
+    }
+    if ($setting == 'settings') {
+      return [];
+    }
+  }
+
+  /**
+   * Get field definition for given field storage definition.
+   *
+   * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $field_storage_definition
+   *   The field storage definition.
+   *
+   * @return \Drupal\Core\Field\BaseFieldDefinition
+   *   The field definition.
+   */
+  protected function getFieldDefinition(FieldStorageDefinitionInterface $field_storage_definition) {
+    return BaseFieldDefinition::createFromFieldStorageDefinition($field_storage_definition);
+  }
+
+  /**
+   * Get all available formatters by loading available ones and filtering out.
+   *
+   * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $field_storage_definition
+   *   The field storage definition.
+   *
+   * @return string[]
+   *   The field formatter labels keys by plugin ID.
+   */
+  protected function getAvailableFormatterOptions(FieldStorageDefinitionInterface $field_storage_definition) {
+    $field_definition = $this->getFieldDefinition($field_storage_definition);
+    $formatters = $this->formatterPluginManager->getOptions($field_storage_definition->getType());
+    $formatter_instances = array_map(function($formatter_id) use ($field_definition) {
+      $configuration = [
+        'field_definition' => $field_definition,
+        'settings' => [],
+        'label' => '',
+        'view_mode' => '',
+        'third_party_settings' => [],
+      ];
+      return $this->formatterPluginManager->createInstance($formatter_id, $configuration);
+    }, array_combine(array_keys($formatters), array_keys($formatters)));
+    $filtered_formatter_instances = array_filter($formatter_instances, function (FormatterInterface $formatter) use ($field_definition) {
+      return $formatter->isApplicable($field_definition);
+    });
+    $options = array_map(function (FormatterInterface $formatter) {
+      return $formatter->getPluginDefinition()['label'];
+    }, $filtered_formatter_instances);
+    return $options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $output = [
+      '#theme' => 'item_list',
+    ];
+    foreach ($this->settings['formatter'] as $bundle => $setting) {
+      $output['#items'][] = [
+        '#markup' => $setting['type'],
+      ];
+    }
+    return $output;
+  }
+
+
+}
diff --git a/tests/src/Kernel/Plugin/Field/FieldFormatter/FieldFormatterPerBundleTest.php b/tests/src/Kernel/Plugin/Field/FieldFormatter/FieldFormatterPerBundleTest.php
new file mode 100644
index 0000000..911b5ca
--- /dev/null
+++ b/tests/src/Kernel/Plugin/Field/FieldFormatter/FieldFormatterPerBundleTest.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace Drupal\Tests\field_formatter\Kernel\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Entity\Entity\EntityViewDisplay;
+use Drupal\entity_test\Entity\EntityTest;
+use Drupal\entity_test\Entity\EntityTestBundle;
+use Drupal\entity_test\Entity\EntityTestWithBundle;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\user\Entity\Role;
+use Drupal\user\Entity\User;
+
+/**
+ * @coversDefaultClass \Drupal\field_formatter\Plugin\Field\FieldFormatter\FieldFormatterPerBundle
+ * @group field_formatter
+ */
+class FieldFormatterPerBundleTest extends KernelTestBase {
+
+  /**
+   * Admin user.
+   *
+   * @var \Drupal\User\UserInterface
+   */
+  protected $adminUser;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'entity_test',
+    'user',
+    'field',
+    'field_formatter',
+    'system',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installSchema('system', ['sequences']);
+    $this->installEntitySchema('entity_test');
+    $this->installEntitySchema('entity_test_with_bundle');
+    $this->installEntitySchema('user');
+
+    $admin_role = Role::create([
+      'id' => 'admin',
+      'permissions' => ['view test entity'],
+    ]);
+    $admin_role->save();
+
+    $this->adminUser = User::create([
+      'name' => $this->randomMachineName(),
+      'roles' => [$admin_role->id()],
+    ]);
+    $this->adminUser->save();
+    \Drupal::currentUser()->setAccount($this->adminUser);
+  }
+
+  /**
+   * Tests field_formatter__per_bundle formatter output.
+   *
+   * @covers ::viewElements
+   * @covers ::getAvailableFieldNames
+   * @covers ::getViewDisplay
+   */
+  public function testRender() {
+    $field_storage = FieldStorageConfig::create([
+      'field_name' => 'test_er_field',
+      'entity_type' => 'entity_test',
+      'type' => 'entity_reference',
+      'settings' => [
+        'target_type' => 'entity_test_with_bundle',
+      ],
+    ]);
+    $field_storage->save();
+
+    $field_config = FieldConfig::create([
+      'field_name' => 'test_er_field',
+      'entity_type' => 'entity_test',
+      'bundle' => 'entity_test',
+    ]);
+    $field_config->save();
+
+    $parent_entity_view_display = EntityViewDisplay::create([
+      'targetEntityType' => 'entity_test',
+      'bundle' => 'entity_test',
+      'mode' => 'default',
+      'content' => [],
+    ]);
+    $parent_entity_view_display->setComponent('test_er_field', [
+      'type' => 'field_formatter__per_bundle',
+      'settings' => [
+        'formatter' => [
+          'bundle1' => [
+            'type' => 'entity_reference_entity_id',
+          ],
+          'bundle2' => [
+            'type' => 'entity_reference_label',
+            'settings' => [
+              'link' => TRUE,
+            ],
+          ],
+        ],
+      ],
+    ]);
+    $parent_entity_view_display->save();
+
+    $child_entity_bundle1 = EntityTestBundle::create([
+      'id' => 'bundle1',
+    ]);
+    $child_entity_bundle1->save();
+    $child_entity_bundle2 = EntityTestBundle::create([
+      'id' => 'bundle2',
+    ]);
+    $child_entity_bundle2->save();
+
+    $child_entity1 = EntityTestWithBundle::create([
+      'name' => ['child name'],
+      'type' => 'bundle1',
+    ]);
+    $child_entity1->save();
+    $child_entity2 = EntityTestWithBundle::create([
+      'name' => ['child name'],
+      'type' => 'bundle2',
+    ]);
+    $child_entity2->save();
+
+    $entity = EntityTest::create([
+      'test_er_field' => [
+        ['target_id' => $child_entity1->id()],
+        ['target_id' => $child_entity2->id()],
+      ],
+    ]);
+    $entity->save();
+
+    $build = $parent_entity_view_display->build($entity);
+
+    \Drupal::service('renderer')->renderRoot($build);
+
+    $expected_output = <<<EXPECTED
+
+  <div>
+    <div>test_er_field</div>
+              <div>
+  <div>
+    <div>test_er_field</div>
+              <div>1</div>
+          </div>
+</div>
+          <div>
+  <div>
+    <div>test_er_field</div>
+              <div><a href="/entity_test_with_bundle/2" hreflang="en">child name</a></div>
+          </div>
+</div>
+          </div>
+
+EXPECTED;
+
+    $this->assertEquals($expected_output, $build['test_er_field']['#markup']);
+  }
+
+}
