diff --git a/core/lib/Drupal/Core/Render/Element/MachineName.php b/core/lib/Drupal/Core/Render/Element/MachineName.php
index 66c85c7..58402d0 100644
--- a/core/lib/Drupal/Core/Render/Element/MachineName.php
+++ b/core/lib/Drupal/Core/Render/Element/MachineName.php
@@ -170,8 +170,24 @@ public static function processMachineName(&$element, FormStateInterface $form_st
     $key_exists = NULL;
     $source = NestedArray::getValue($form_state->getCompleteForm(), $element['#machine_name']['source'], $key_exists);
     if (!$key_exists) {
+      // Try to find the source element by looking up the parents of the machine
+      // name element.
+      $element_parents = $element['#array_parents'];
+
+      // Remove the element itself from the array.
+      array_pop($element_parents);
+      $source_parents = array_merge($element_parents, $element['#machine_name']['source']);
+      $source = NestedArray::getValue($form_state->getCompleteForm(), $source_parents, $key_exists);
+    }
+
+    if (!$key_exists) {
       return $element;
     }
+    elseif (isset($source_parents)) {
+      // The source element was found in the form in a different location than
+      // initially specified so we need to update it.
+      $element['#machine_name']['source'] = $source_parents;
+    }
 
     $suffix_id = $source['#id'] . '-machine-name-suffix';
     $element['#machine_name']['suffix'] = '#' . $suffix_id;
diff --git a/core/modules/field/config/schema/field.schema.yml b/core/modules/field/config/schema/field.schema.yml
index 55760a7..26b156c 100644
--- a/core/modules/field/config/schema/field.schema.yml
+++ b/core/modules/field/config/schema/field.schema.yml
@@ -24,6 +24,9 @@ field.storage.*.*:
     type:
       type: string
       label: 'Type'
+    label:
+      type: label
+      label: 'Label'
     settings:
       type: field.storage_settings.[%parent.type]
     module:
diff --git a/core/modules/field/src/Entity/FieldStorageConfig.php b/core/modules/field/src/Entity/FieldStorageConfig.php
index 5fff1aa..b07ef69 100644
--- a/core/modules/field/src/Entity/FieldStorageConfig.php
+++ b/core/modules/field/src/Entity/FieldStorageConfig.php
@@ -28,13 +28,14 @@
  *   config_prefix = "storage",
  *   entity_keys = {
  *     "id" = "id",
- *     "label" = "id"
+ *     "label" = "label"
  *   },
  *   config_export = {
  *     "id",
  *     "field_name",
  *     "entity_type",
  *     "type",
+ *     "label",
  *     "settings",
  *     "module",
  *     "locked",
@@ -95,6 +96,16 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
   protected $type;
 
   /**
+   * The human-readable label for the field storage.
+   *
+   * This will be used as the default title for new fields using this field
+   * storage.
+   *
+   * @var string
+   */
+  protected $label;
+
+  /**
    * The name of the module that provides the field type.
    *
    * @var string
@@ -237,12 +248,12 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
    */
   public function __construct(array $values, $entity_type = 'field_storage_config') {
     // Check required properties.
-    if (empty($values['field_name'])) {
-      throw new FieldException('Attempt to create a field storage without a field name.');
-    }
-    if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $values['field_name'])) {
-      throw new FieldException("Attempt to create a field storage {$values['field_name']} with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character");
-    }
+//    if (empty($values['field_name'])) {
+//      throw new FieldException('Attempt to create a field storage without a field name.');
+//    }
+//    if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $values['field_name'])) {
+//      throw new FieldException("Attempt to create a field storage {$values['field_name']} with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character");
+//    }
     if (empty($values['type'])) {
       throw new FieldException("Attempt to create a field storage {$values['field_name']} with no type.");
     }
@@ -687,7 +698,7 @@ public function isQueryable() {
    *   TRUE if the field has data for any entity; FALSE otherwise.
    */
   public function hasData() {
-    return \Drupal::entityManager()->getStorage($this->entity_type)->countFieldData($this, TRUE);
+    return !$this->isNew() && \Drupal::entityManager()->getStorage($this->entity_type)->countFieldData($this, TRUE);
   }
 
   /**
diff --git a/core/modules/field_ui/src/Form/FieldStorageAddForm.php b/core/modules/field_ui/src/Form/FieldStorageAddForm.php
index 5f087a6..9ef499a 100644
--- a/core/modules/field_ui/src/Form/FieldStorageAddForm.php
+++ b/core/modules/field_ui/src/Form/FieldStorageAddForm.php
@@ -7,13 +7,14 @@
 
 namespace Drupal\field_ui\Form;
 
-use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Entity\EntityFormBuilderInterface;
 use Drupal\Core\Entity\Query\QueryFactory;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Field\FieldTypePluginManagerInterface;
 use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormState;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\Core\Render\Element;
 use Drupal\field\FieldStorageConfigInterface;
 use Drupal\field_ui\FieldUI;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -59,11 +60,11 @@ class FieldStorageAddForm extends FormBase {
   public $queryFactory;
 
   /**
-   * The configuration factory.
+   * The entity form builder.
    *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   * @var \Drupal\Core\Entity\EntityFormBuilderInterface
    */
-  protected $configFactory;
+  protected $entityFormBuilder;
 
   /**
    * Constructs a new FieldStorageAddForm object.
@@ -74,14 +75,14 @@ class FieldStorageAddForm extends FormBase {
    *   The field type plugin manager.
    * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
    *   The entity query factory.
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *   The configuration factory.
+   * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entity_form_builder
+   *   The entity form builder.
    */
-  public function __construct(EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_plugin_manager, QueryFactory $query_factory, ConfigFactoryInterface $config_factory) {
+  public function __construct(EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_plugin_manager, QueryFactory $query_factory, EntityFormBuilderInterface $entity_form_builder) {
     $this->entityManager = $entity_manager;
     $this->fieldTypePluginManager = $field_type_plugin_manager;
     $this->queryFactory = $query_factory;
-    $this->configFactory = $config_factory;
+    $this->entityFormBuilder = $entity_form_builder;
   }
 
   /**
@@ -99,7 +100,7 @@ public static function create(ContainerInterface $container) {
       $container->get('entity.manager'),
       $container->get('plugin.manager.field.field_type'),
       $container->get('entity.query'),
-      $container->get('config.factory')
+      $container->get('entity.form_builder')
     );
   }
 
@@ -135,6 +136,10 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t
       '#title' => $this->t('Add a new field'),
       '#options' => $field_type_options,
       '#empty_option' => $this->t('- Select a field type -'),
+      '#ajax' => array(
+        'callback' => '::buildAjaxFieldStorageConfig',
+        'wrapper' => 'new-storage-wrapper',
+      ),
     );
 
     // Re-use existing field.
@@ -150,7 +155,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t
         '#empty_option' => $this->t('- Select an existing field -'),
       );
 
-      $form['#attached']['drupalSettings']['existingFieldLabels'] = $this->getExistingFieldLabels(array_keys($existing_field_storage_options));
+      $form['#attached']['drupalSettings']['existingFieldLabels'] = $this->getExistingFieldStorageLabels(array_keys($existing_field_storage_options));
     }
     else {
       // Provide a placeholder form element to simplify the validation code.
@@ -161,37 +166,36 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t
     }
 
     // Field label and field_name.
-    $form['new_storage_wrapper'] = array(
+    $form['new_storage_wrapper'] = [
       '#type' => 'container',
-      '#states' => array(
-        '!visible' => array(
-          ':input[name="new_storage_type"]' => array('value' => ''),
-        ),
-      ),
-    );
-    $form['new_storage_wrapper']['label'] = array(
-      '#type' => 'textfield',
-      '#title' => $this->t('Label'),
-      '#size' => 15,
-    );
+      '#attributes' => [
+        'id' => 'new-storage-wrapper',
+      ],
+    ];
 
-    $field_prefix = $this->config('field_ui.settings')->get('field_prefix');
-    $form['new_storage_wrapper']['field_name'] = array(
-      '#type' => 'machine_name',
-      // This field should stay LTR even for RTL languages.
-      '#field_prefix' => '<span dir="ltr">' . $field_prefix,
-      '#field_suffix' => '</span>&lrm;',
-      '#size' => 15,
-      '#description' => $this->t('A unique machine-readable name containing letters, numbers, and underscores.'),
-      // Calculate characters depending on the length of the field prefix
-      // setting. Maximum length is 32.
-      '#maxlength' => FieldStorageConfig::NAME_MAX_LENGTH - strlen($field_prefix),
-      '#machine_name' => array(
-        'source' => array('new_storage_wrapper', 'label'),
-        'exists' => array($this, 'fieldNameExists'),
-      ),
-      '#required' => FALSE,
-    );
+    if ($form_state->isRebuilding() && ($new_storage_type = $form_state->getValue('new_storage_type'))) {
+      $initial_values = $this->getInitialValues($new_storage_type);
+
+      $field_storage_values = [
+        'entity_type' => $form_state->get('entity_type_id'),
+        'type' => $initial_values['type'],
+      ] + $initial_values['field_storage'];
+      $field_storage = $this->entityManager->getStorage('field_storage_config')->create($field_storage_values);
+
+      $form_object = $this->entityManager->getFormObject('field_storage_config', 'edit');
+      $form_object->setEntity($field_storage);
+
+      $form_state = (new FormState())->setFormState([
+        'entity_type_id' => $form_state->get('entity_type_id'),
+        'bundle' => $form_state->get('bundle'),
+      ]);
+
+      $field_storage_form = $form_object->form([], $form_state);
+      unset($field_storage_form['#process'], $field_storage_form['#after_build']);
+      $field_storage_form['cardinality_container']['#parents'] = ['new_storage_wrapper'];
+
+      $form['new_storage_wrapper'] += $field_storage_form;
+    }
 
     // Provide a separate label element for the "Re-use existing field" case
     // and place it outside the $form['add'] wrapper because those elements
@@ -231,6 +235,13 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t
   }
 
   /**
+   * Handles changes to the selected field storage type.
+   */
+  public function buildAjaxFieldStorageConfig(array $form, FormStateInterface $form_state) {
+    return $form['new_storage_wrapper'];
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function validateForm(array &$form, FormStateInterface $form_state) {
@@ -261,24 +272,9 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
    */
   protected function validateAddNew(array $form, FormStateInterface $form_state) {
     // Validate if any information was provided in the 'add new field' case.
-    if ($form_state->getValue('new_storage_type')) {
-      // Missing label.
-      if (!$form_state->getValue('label')) {
-        $form_state->setErrorByName('label', $this->t('Add new field: you need to provide a label.'));
-      }
-
-      // Missing field name.
-      if (!$form_state->getValue('field_name')) {
-        $form_state->setErrorByName('field_name', $this->t('Add new field: you need to provide a machine name for the field.'));
-      }
-      // Field name validation.
-      else {
-        $field_name = $form_state->getValue('field_name');
-
-        // Add the field prefix.
-        $field_name = $this->configFactory->get('field_ui.settings')->get('field_prefix') . $field_name;
-        $form_state->setValueForElement($form['new_storage_wrapper']['field_name'], $field_name);
-      }
+    if ($form_state->isRebuilding() && $form_state->getValue('new_storage_type')) {
+      $form_object = $this->entityManager->getFormObject('field_storage_config', 'edit');
+      $form_object->validateForm($form['new_storage_wrapper'], $form_state);
     }
   }
 
@@ -312,12 +308,15 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
 
     // Create new field.
     if ($values['new_storage_type']) {
+      $preconfigured_values = $this->getInitialValues($values['new_storage_type']);
+
       $field_storage_values = [
+        'type' => $preconfigured_values['type'],
         'field_name' => $values['field_name'],
         'entity_type' => $this->entityTypeId,
-        'type' => $values['new_storage_type'],
         'translatable' => $values['translatable'],
-      ];
+      ] + $preconfigured_values['field_storage'];
+
       $field_values = [
         'field_name' => $values['field_name'],
         'entity_type' => $this->entityTypeId,
@@ -325,41 +324,21 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         'label' => $values['label'],
         // Field translatability should be explicitly enabled by the users.
         'translatable' => FALSE,
-      ];
-      $widget_id = $formatter_id = NULL;
-
-      // Check if we're dealing with a preconfigured field.
-      if (strpos($field_storage_values['type'], 'field_ui:') !== FALSE) {
-        list(, $field_type, $option_key) = explode(':', $field_storage_values['type'], 3);
-        $field_storage_values['type'] = $field_type;
-
-        $field_type_class = $this->fieldTypePluginManager->getDefinition($field_type)['class'];
-        $field_options = $field_type_class::getPreconfiguredOptions()[$option_key];
-
-        // Merge in preconfigured field storage options.
-        if (isset($field_options['field_storage_config'])) {
-          foreach (array('cardinality', 'settings') as $key) {
-            if (isset($field_options['field_storage_config'][$key])) {
-              $field_storage_values[$key] = $field_options['field_storage_config'][$key];
-            }
-          }
-        }
-
-        // Merge in preconfigured field options.
-        if (isset($field_options['field_config'])) {
-          foreach (array('required', 'settings') as $key) {
-            if (isset($field_options['field_config'][$key])) {
-              $field_values[$key] = $field_options['field_config'][$key];
-            }
-          }
-        }
+      ] + $preconfigured_values['field'];
 
-        $widget_id = isset($field_options['entity_form_display']['type']) ? $field_options['entity_form_display']['type'] : NULL;
-        $formatter_id = isset($field_options['entity_view_display']['type']) ? $field_options['entity_view_display']['type'] : NULL;
-      }
+      $widget_id = $preconfigured_values['widget_id'];
+      $formatter_id = $preconfigured_values['formatter_id'];
 
       // Create the field storage and field.
       try {
+        // Merge in the values from the field storage edit subform.
+        $field_storage = $this->entityManager->getStorage('field_storage_config')->create($field_storage_values);
+
+        $form_object = $this->entityManager->getFormObject('field_storage_config', 'edit');
+        $form_object->setEntity($field_storage);
+        $form_object->submitForm($form['new_storage_wrapper'], $form_state);
+        $field_storage_values = $form_object->getEntity()->toArray() + $field_storage_values;
+
         $this->entityManager->getStorage('field_storage_config')->create($field_storage_values)->save();
         $field = $this->entityManager->getStorage('field_config')->create($field_values);
         $field->save();
@@ -372,7 +351,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         $route_parameters = array(
           'field_config' => $field->id(),
         ) + FieldUI::getRouteBundleParameter($entity_type, $this->bundle);
-        $destinations[] = array('route_name' => "entity.field_config.{$this->entityTypeId}_storage_edit_form", 'route_parameters' => $route_parameters);
         $destinations[] = array('route_name' => "entity.field_config.{$this->entityTypeId}_field_edit_form", 'route_parameters' => $route_parameters);
         $destinations[] = array('route_name' => "entity.{$this->entityTypeId}.field_ui_fields", 'route_parameters' => $route_parameters);
 
@@ -427,6 +405,62 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
   }
 
   /**
+   * Gets the default properties for the config entities created by this form.
+   *
+   * @param string $field_type
+   *   The field type selection from the 'new storage type' form element.
+   *
+   * @return array
+   *   An array with the following structure:
+   *   - type: (string) The field type plugin ID.
+   *   - field_storage: (array) The default properties of a field storage
+   *     config.
+   *   - field: (array) The default properties of a field config.
+   *   - widget_id: (string) The default widget plugin ID.
+   *   - formatter_id: (string) The default formatter plugin ID.
+   */
+  protected function getInitialValues($field_type) {
+    $initial_values = [
+      'type' => $field_type,
+      'field_storage' => [],
+      'field' => [],
+      'widget_id' => NULL,
+      'formatter_id' => NULL,
+    ];
+
+    if (strpos($field_type, 'field_ui:') !== FALSE) {
+      list(, $field_type, $option_key) = explode(':', $field_type, 3);
+      $initial_values['type'] = $field_type;
+
+      $field_type_class = $this->fieldTypePluginManager->getDefinition($field_type)['class'];
+      $field_options = $field_type_class::getPreconfiguredOptions()[$option_key];
+
+      // Add pre-configured field storage options.
+      if (isset($field_options['field_storage_config'])) {
+        foreach (array('cardinality', 'settings') as $key) {
+          if (isset($field_options['field_storage_config'][$key])) {
+            $initial_values['field_storage'][$key] = $field_options['field_storage_config'][$key];
+          }
+        }
+      }
+
+      // Add pre-configured field options.
+      if (isset($field_options['field_config'])) {
+        foreach (array('required', 'settings') as $key) {
+          if (isset($field_options['field_config'][$key])) {
+            $initial_values['field'][$key] = $field_options['field_config'][$key];
+          }
+        }
+      }
+
+      $initial_values['widget_id'] = isset($field_options['entity_form_display']['type']) ? $field_options['entity_form_display']['type'] : NULL;
+      $initial_values['formatter_id'] = isset($field_options['entity_view_display']['type']) ? $field_options['entity_view_display']['type'] : NULL;
+    }
+
+    return $initial_values;
+  }
+
+  /**
    * Configures the newly created field for the default view and form modes.
    *
    * @param string $field_name
@@ -497,64 +531,25 @@ protected function getExistingFieldStorageOptions() {
   /**
    * Gets the human-readable labels for the given field storage names.
    *
-   * Since not all field storages are required to have a field, we can only
-   * provide the field labels on a best-effort basis (e.g. the label of a field
-   * storage without any field attached to a bundle will be the field name).
-   *
    * @param array $field_names
    *   An array of field names.
    *
    * @return array
    *   An array of field labels keyed by field name.
    */
-  protected function getExistingFieldLabels(array $field_names) {
-    // Get all the fields corresponding to the given field storage names and
-    // this entity type.
-    $field_ids = $this->queryFactory->get('field_config')
-      ->condition('entity_type', $this->entityTypeId)
-      ->condition('field_name', $field_names)
-      ->execute();
-    $fields = $this->entityManager->getStorage('field_config')->loadMultiple($field_ids);
-
-    // Go through all the fields and use the label of the first encounter.
-    $labels = array();
-    foreach ($fields as $field) {
-      if (!isset($labels[$field->getName()])) {
-        $labels[$field->getName()] = $field->label();
-      }
+  protected function getExistingFieldStorageLabels(array $field_names) {
+    $field_ids = [];
+    foreach ($field_names as $field_name) {
+      $field_ids[] = $this->entityTypeId . '.' . $field_name;
     }
+    $field_storages = $this->entityManager->getStorage('field_storage_config')->loadMultiple($field_ids);
 
-    // For field storages without any fields attached to a bundle, the default
-    // label is the field name.
-    $labels += array_combine($field_names, $field_names);
-
-    return $labels;
-  }
-
-  /**
-   * Checks if a field machine name is taken.
-   *
-   * @param string $value
-   *   The machine name, not prefixed.
-   * @param array $element
-   *   An array containing the structure of the 'field_name' element.
-   * @param \Drupal\Core\Form\FormStateInterface $form_state
-   *   The current state of the form.
-   *
-   * @return bool
-   *   Whether or not the field machine name is taken.
-   */
-  public function fieldNameExists($value, $element, FormStateInterface $form_state) {
-    // Don't validate the case when an existing field has been selected.
-    if ($form_state->getValue('existing_storage_name')) {
-      return FALSE;
+    $labels = array();
+    foreach ($field_storages as $field_storage) {
+      $labels[$field_storage->getName()] = $field_storage->label();
     }
 
-    // Add the field prefix.
-    $field_name = $this->configFactory->get('field_ui.settings')->get('field_prefix') . $value;
-
-    $field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($this->entityTypeId);
-    return isset($field_storage_definitions[$field_name]);
+    return $labels;
   }
 
 }
diff --git a/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php b/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php
index adafcc7..473bfab 100644
--- a/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php
+++ b/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php
@@ -8,11 +8,16 @@
 namespace Drupal\field_ui\Form;
 
 use Drupal\Core\Entity\EntityForm;
+use Drupal\Core\Field\BaseFieldDefinition;
+use Drupal\Core\Field\FieldItemList;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Field\FieldTypePluginManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\field_ui\FieldUI;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Provides a form for the "field storage" edit page.
@@ -27,6 +32,32 @@ class FieldStorageConfigEditForm extends EntityForm {
   protected $entity;
 
   /**
+   * The field type plugin manager.
+   *
+   * @var \Drupal\Core\Field\FieldTypePluginManagerInterface
+   */
+  protected $fieldTypePluginManager;
+
+  /**
+   * Constructs a new FieldStorageConfigEditForm.
+   *
+   * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
+   *   The field type manager.
+   */
+  public function __construct(FieldTypePluginManagerInterface $field_type_manager) {
+    $this->fieldTypePluginManager = $field_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('plugin.manager.field.field_type')
+    );
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) {
@@ -61,16 +92,50 @@ public function buildForm(array $form, FormStateInterface $form_state, $field_co
   public function form(array $form, FormStateInterface $form_state) {
     $form = parent::form($form, $form_state);
 
-    $field_label = $form_state->get('field_config')->label();
-    $form['#title'] = $field_label;
-    $form['#prefix'] = '<p>' . $this->t('These settings apply to the %field field everywhere it is used. These settings impact the way that data is stored in the database and cannot be changed once data has been created.', array('%field' => $field_label)) . '</p>';
+    // We cannot use an 'add' entity form operation because this form is also
+    // used as an AJAX subform of \Drupal\field_ui\Form\FieldStorageAddForm.
+    if (!$this->entity->isNew()) {
+      $field_label = $form_state->get('field_config')->label();
+      $form['#title'] = $field_label;
+      $form['#prefix'] = '<p>' . $this->t('These settings apply to the %field field everywhere it is used. These settings impact the way that data is stored in the database and cannot be changed once data has been created.', array('%field' => $field_label)) . '</p>';
 
-    // See if data already exists for this field.
-    // If so, prevent changes to the field settings.
-    if ($this->entity->hasData()) {
-      $form['#prefix'] = '<div class="messages messages--error">' . $this->t('There is data for this field in the database. The field settings can no longer be changed.') . '</div>' . $form['#prefix'];
+      // See if data already exists for this field.
+      // If so, prevent changes to the field settings.
+      if ($this->entity->hasData()) {
+        $form['#prefix'] = '<div class="messages messages--error">' . $this->t('There is data for this field in the database. The field settings can no longer be changed.') . '</div>' . $form['#prefix'];
+      }
     }
 
+    $form['label'] = array(
+      '#type' => 'textfield',
+      '#title' => $this->t('Label'),
+      '#default_value' => $this->entity->label(),
+      '#size' => 15,
+      '#required' => TRUE,
+      '#weight' => -15,
+    );
+
+    $field_prefix = $this->config('field_ui.settings')->get('field_prefix');
+    $form['field_name'] = array(
+      '#type' => 'machine_name',
+      '#default_value' => $this->entity->getName(),
+      // This field should stay LTR even for RTL languages.
+      '#field_prefix' => '<span dir="ltr">' . $field_prefix,
+      '#field_suffix' => '</span>&lrm;',
+      '#size' => 15,
+      '#description' => $this->t('A unique machine-readable name containing letters, numbers, and underscores.'),
+      // Calculate characters depending on the length of the field prefix
+      // setting. Maximum length is 32.
+      '#maxlength' => FieldStorageConfig::NAME_MAX_LENGTH - strlen($field_prefix),
+      '#machine_name' => array(
+        'source' => array('label'),
+        'exists' => array($this, 'fieldNameExists'),
+      ),
+      '#required' => TRUE,
+      '#access' => $this->entity->isNew(),
+      '#weight' => -14,
+    );
+
     // Add settings provided by the field module. The field module is
     // responsible for not returning settings that cannot be changed if
     // the field already has data.
@@ -86,7 +151,13 @@ public function form(array $form, FormStateInterface $form_state) {
       'entity_id' => NULL
     );
     $entity = _field_create_entity_from_ids($ids);
-    $items = $entity->get($this->entity->getName());
+
+    // @todo Use a proper FieldStorageDefinition class when it becomes available
+    //   in https://www.drupal.org/node/2280639.
+    $field_storage_definition = BaseFieldDefinition::create($this->entity->getType());
+    $field_storage_definition->getItemDefinition()->setSettings($this->entity->getSettings());
+
+    $items = FieldItemList::createInstance($field_storage_definition, NULL, $entity->getTypedData());
     $item = $items->first() ?: $items->appendItem();
     $form['settings'] += $item->storageSettingsForm($form, $form_state, $this->entity->hasData());
 
@@ -153,6 +224,12 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
     if ($form_state->getValue('cardinality') === 'number' && !$form_state->getValue('cardinality_number')) {
       $form_state->setErrorByName('cardinality_number', $this->t('Number of values is required.'));
     }
+
+    // Add the field prefix.
+    if (isset($form['field_name'])) {
+      $field_name = $this->config('field_ui.settings')->get('field_prefix') . $form_state->getValue('field_name');
+      $form_state->setValueForElement($form['field_name'], $field_name);
+    }
   }
 
   /**
@@ -189,4 +266,25 @@ public function save(array $form, FormStateInterface $form_state) {
     }
   }
 
+  /**
+   * Checks if a field machine name is taken.
+   *
+   * @param string $value
+   *   The machine name, not prefixed.
+   * @param array $element
+   *   An array containing the structure of the 'field_name' element.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   *
+   * @return bool
+   *   Whether or not the field machine name is taken.
+   */
+  public function fieldNameExists($value, $element, FormStateInterface $form_state) {
+    // Add the field prefix.
+    $field_name = $this->config('field_ui.settings')->get('field_prefix') . $value;
+
+    $field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($form_state->get('entity_type_id'));
+    return isset($field_storage_definitions[$field_name]);
+  }
+
 }
