diff --git a/modules/contrib/shs/js/models/WidgetModel.js b/modules/contrib/shs/js/models/WidgetModel.js
index d62b4f4..92db91c 100644
--- a/modules/contrib/shs/js/models/WidgetModel.js
+++ b/modules/contrib/shs/js/models/WidgetModel.js
@@ -32,6 +32,11 @@
       defaultValue: '_none',
 
       /**
+       * The new item that was created.
+       */
+      createValue: null,
+      
+      /**
        * Position of widget in app.
        *
        * @type {integer}
diff --git a/modules/contrib/shs/js/views/AppView.js b/modules/contrib/shs/js/views/AppView.js
index 8693214..fe20ca3 100644
--- a/modules/contrib/shs/js/views/AppView.js
+++ b/modules/contrib/shs/js/views/AppView.js
@@ -65,9 +65,6 @@
           parents: parents
         }));
       });
-//      $.each(app.getConfig('parents'), function (index, item) {
-//        // Add WidgetModel for each parent.
-//      });
 
       app.collection.trigger('initialize:shs');
 
@@ -127,6 +124,19 @@
           // Use value of parent widget (which is the id of the model ;)).
           value = widgetModel.get('id');
         }
+        else if (widgetModel.get('createValue')) {
+          // Add the created item to the original select item.
+          var options = $("option", app.$el).map(function () {
+            return $(this).val();
+          }).get();
+          if ($.inArray(value, options) === -1) {
+            var item = widgetModel.get('createValue');
+            app.$el.append($("<option/>").val(item.tid).text(item.name));
+            // We can now reset our widget model to the new tid.
+            widgetModel.set('createValue', null);
+            widgetModel.set('defaultValue', item.tid);
+          }
+        }
       }
       // Set the updated value.
       app.$el.val(value).trigger({
diff --git a/modules/contrib/shs/js/views/ContainerView.js b/modules/contrib/shs/js/views/ContainerView.js
index ad98e3b..30b7364 100644
--- a/modules/contrib/shs/js/views/ContainerView.js
+++ b/modules/contrib/shs/js/views/ContainerView.js
@@ -119,7 +119,14 @@
       container.collection.remove(models);
 
       var anyValue = container.app.getSetting('anyValue');
-      if (value !== anyValue) {
+      var createValue = container.app.getSetting('createValue');
+
+      if (value === createValue && widgetModel.get('createValue')) {
+        var item = widgetModel.get('createValue');
+        value = item.tid;
+      }
+
+      if ((value !== anyValue) && (value !== createValue)) {
         // Add new model with current selection.
         container.collection.add(new Drupal.shs.classes[container.app.getConfig('fieldName')].models.widget({
           id: value,
@@ -130,7 +137,7 @@
         // Use value of parent widget (which is the id of the model ;)).
         value = widgetModel.get('id');
       }
-
+      
       // Update parents.
       var parents = [];
       var previousParent = 0;
diff --git a/modules/contrib/shs/js/views/WidgetView.js b/modules/contrib/shs/js/views/WidgetView.js
index 3cf9459..4bff698 100644
--- a/modules/contrib/shs/js/views/WidgetView.js
+++ b/modules/contrib/shs/js/views/WidgetView.js
@@ -91,6 +91,11 @@
       // Add "any" option.
       widget.$el.append($('<option>').text(widget.container.app.getSetting('anyLabel')).val(widget.container.app.getSetting('anyValue')));
 
+      // Add "create" option.
+      if (widget.container.app.getSetting('create_new_items')) {
+        widget.$el.append($('<option>').text(widget.container.app.getSetting('createLabel')).val(widget.container.app.getSetting('createValue')));
+      }
+
       // Create options from collection.
       widget.model.itemCollection.each(function (item) {
         if (!item.get('tid')) {
@@ -138,6 +143,67 @@
         $container.append(widget.$el.fadeIn(widget.container.app.getConfig('display.animationSpeed')));
       }
 
+      var createValue = widget.container.app.getSetting('createValue');
+      if (widget.$el.val() == createValue) {
+        var create_item_input_id = 'shs-widget-create-new-item-' + widget.container.app.getConfig('fieldName');
+        $container.append($('<input>')
+            .on('keyup', function(e) {
+              if (e.keyCode == 13) {
+                // Do something
+                $('#' + create_item_input_id + '_button').trigger('click');
+                e.preventDefault();
+                return false;
+              }
+            })
+            .attr('type', 'text')
+            .attr('id', create_item_input_id)
+            .attr('name', 'create_new_item')
+        ).append($('<button>')
+            .attr('id', create_item_input_id + '_button')
+            .html('Create')
+            .on('click', function(e) {
+                var value = $('#' + create_item_input_id).val();
+
+                // Get the langcode value if present.
+                var $language = $('select[name="langcode[0][value]"]');
+                var langcode = 'und';
+                if ($language) {
+                  langcode = $language.val();
+                }
+
+                $.ajax({
+                  url: widget.container.app.getConfig('createUrl'),
+                  type: 'POST',
+                  dataType: 'json',
+                  async: false,
+                  contentType: 'application/json',
+                  Accept: 'application/json',
+                  data: JSON.stringify({
+                    arguments: {
+                      value: value,
+                      bundle: widget.container.app.getConfig('bundle'),
+                      entity_id: widget.model.get('id'),
+                      langcode: langcode
+                    }
+                  })
+                }).then(function(data) {
+                  if (data !== 'null') {
+                    // Force a reload.
+                    widget.model.set('dataLoaded', false);
+
+                    // Update create value of attached model.
+                    widget.model.set('createValue', data);
+
+                    // Fire events.
+                    widget.container.collection.trigger('update:selection', widget.model, widget.model.get('defaultValue'), widget);
+                  }
+                });
+
+                e.preventDefault();
+                return false;
+            })
+        );
+      }
       widget.model.set('dataLoaded', true);
       // Return self for chaining.
       return widget;
diff --git a/modules/contrib/shs/shs.module b/modules/contrib/shs/shs.module
index 1876d7f..eeeb0b5 100644
--- a/modules/contrib/shs/shs.module
+++ b/modules/contrib/shs/shs.module
@@ -79,7 +79,7 @@ function shs_term_get_parents($default_values, $settings, $target_type) {
       $storage = Drupal::entityTypeManager()->getStorage($target_type);
       $parent_terms = array_reverse(array_keys($storage->loadAllParents($value)));
       $keys = array_merge([0], $parent_terms);
-      $values = array_merge($parent_terms, [$value]);
+      $values = array_merge($parent_terms, [$settings['anyValue']]);
       $parents[$delta] = [];
       foreach ($keys as $index => $key) {
         $parents[$delta][] = [
diff --git a/modules/contrib/shs/shs.routing.yml b/modules/contrib/shs/shs.routing.yml
index cf93fd9..f4e602e 100644
--- a/modules/contrib/shs/shs.routing.yml
+++ b/modules/contrib/shs/shs.routing.yml
@@ -6,3 +6,11 @@ shs.term_data:
     entity_id: null
   requirements:
     _permission: 'access content'
+
+shs.create_term:
+  path: '/shs-create-term'
+  defaults:
+    _controller: '\Drupal\shs\Controller\ShsController::createTerm'
+  requirements:
+    _csrf_token: 'TRUE'
+    _custom_access:  '\Drupal\shs\Controller\ShsController::createTermAccess'
diff --git a/modules/contrib/shs/src/Controller/ShsController.php b/modules/contrib/shs/src/Controller/ShsController.php
index 6e4381c..f63b372 100644
--- a/modules/contrib/shs/src/Controller/ShsController.php
+++ b/modules/contrib/shs/src/Controller/ShsController.php
@@ -2,10 +2,16 @@
 
 namespace Drupal\shs\Controller;
 
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Cache\CacheableJsonResponse;
 use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Session\AccountInterface;
 use Drupal\shs\Cache\ShsCacheableJsonResponse;
 use Drupal\shs\Cache\ShsTermCacheDependency;
+use Drupal\taxonomy\Entity\Vocabulary;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Controller for getting taxonomy terms.
@@ -80,4 +86,93 @@ public function getTermData($identifier, $bundle, $entity_id = 0) {
     return $response;
   }
 
+  /**
+   * Create term data.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *
+   * @return JsonResponse
+   *   Json response.
+   */
+  public function createTerm(Request $request) {
+
+    $result = NULL;
+
+    // Obtain the data from the json.
+    $data = json_decode($request->getContent());
+    $value = $data->arguments->value;
+    $bundle = $data->arguments->bundle;
+    $entity_id = $data->arguments->entity_id;
+    $langcode = $data->arguments->langcode;
+
+    if (!$langcode) {
+      $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
+    }
+
+    $entity_manager = \Drupal::getContainer()->get('entity.manager');
+    $storage = $entity_manager->getStorage('taxonomy_term');
+
+    // Try to find the term.
+    $found = null;
+    $terms = $storage->loadTree($bundle, $entity_id, 1, TRUE);
+    foreach ($terms as $term) {
+      if ($term->hasTranslation($langcode)) {
+        $term = $term->getTranslation($langcode);
+      }
+      else {
+        $langcode = $term->default_langcode;
+      }
+
+      if (strcasecmp($term->getName(), $value) === 0) {
+        $found = $term;
+        break;
+      }
+    }
+
+    if (!$found) {
+      $term = $storage->create([
+        'vid' => $bundle,
+        'langcode' => $langcode,
+        'name' => $value,
+        'parent' => array($entity_id),
+      ]);
+      $term->save();
+    }
+    else {
+      $term = $found;
+    }
+
+    $result = (object) [
+      'tid' => $term->id(),
+      'name' => $term->getName(),
+      'description__value' => $term->getDescription(),
+      'langcode' => $langcode,
+      'hasChildren' => shs_term_has_children($term->id()),
+    ];
+
+    $response = new JsonResponse();
+    $response->setData($result);
+
+    return $response;
+  }
+
+  /**
+   * Checks access for a specific request.
+   *
+   * @param \Drupal\Core\Session\AccountInterface $account
+   *   Run access checks for this account.
+   *
+   * @return bool
+   */
+  public function createTermAccess(AccountInterface $account) {
+    $request = \Drupal::request();
+    $data = json_decode($request->getContent());
+    $bundle = $data->arguments->bundle;
+
+    return AccessResult::allowedIfHasPermissions($account, [
+      "edit terms in {$bundle}",
+      'administer taxonomy'
+    ], 'OR');
+  }
+
 }
diff --git a/modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php b/modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php
index 223ca4a..d10b676 100644
--- a/modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php
+++ b/modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php
@@ -2,11 +2,14 @@
 
 namespace Drupal\shs\Plugin\Field\FieldWidget;
 
+use Drupal;
 use Drupal\Component\Utility\Html;
+use Drupal\Core\Entity\FieldableEntityInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\BubbleableMetadata;
 use Drupal\Core\Url;
 
 /**
@@ -47,7 +50,6 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
       '#title' => t('Allow creating new items'),
       '#default_value' => $this->getSetting('create_new_items'),
       '#description' => t('Allow users to create new items of the source bundle.'),
-      '#disabled' => TRUE,
     ];
     $element['create_new_levels'] = [
       '#type' => 'checkbox',
@@ -59,7 +61,6 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
           ':input[name="fields[' . $field_name . '][settings_edit_form][settings][create_new_items]"]' => ['checked' => TRUE],
         ],
       ],
-      '#disabled' => TRUE,
     ];
     $element['force_deepest'] = [
       '#type' => 'checkbox',
@@ -103,6 +104,10 @@ public function settingsSummary() {
    * {@inheritdoc}
    */
   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+
+    // Don't cache because we get illegal choice errors if new items are created.
+    $form_state->disableCache();
+
     $element = parent::formElement($items, $delta, $element, $form, $form_state);
     if (isset($form_state->getBuildInfo()['base_form_id']) && ('field_config_form' === $form_state->getBuildInfo()['base_form_id'])) {
       // Do not display the shs widget in the field config.
@@ -122,6 +127,8 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       'anyLabel' => $this->getEmptyLabel() ?: t('- None -'),
       'anyValue' => '_none',
       'addNewLabel' => t('Add another item'),
+      'createValue' => '_create',
+      'createLabel' => $this->getCreateLabel() ?: t('Create...'),
     ];
 
     $bundle = reset($target_bundles);
@@ -139,10 +146,22 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       $parents = shs_term_get_parents($default_value, $settings_additional, $this->fieldDefinition->getItemDefinition()->getSetting('target_type'));
     }
 
+    // Generate a token for our ajax url.
+    // We need to run this through a render function because Drupal.url generates
+    // a placeholder token.
+    $urlBubbleable = Url::fromRoute('shs.create_term')->toString(TRUE);
+    $urlRender = array(
+      '#markup' => $urlBubbleable->getGeneratedUrl(),
+    );
+    BubbleableMetadata::createFromRenderArray($urlRender)
+      ->merge($urlBubbleable)->applyTo($urlRender);
+    $url = Drupal::service('renderer')->renderPlain($urlRender);
+
     $settings_shs = [
       'settings' => $this->getSettings() + $settings_additional,
       'bundle' => $bundle,
       'baseUrl' => Url::fromUri('base:/shs-term-data')->toString(),
+      'createUrl' => $url,
       'cardinality' => $this->fieldDefinition->getFieldStorageDefinition()->getCardinality(),
       'parents' => $parents,
       'defaultValue' => $default_value,
@@ -153,7 +172,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       "shs_{$field_name}_js_settings",
     ];
     // Allow other modules to override the settings.
-    \Drupal::moduleHandler()->alter($hooks, $settings_shs, $bundle, $field_name);
+    Drupal::moduleHandler()->alter($hooks, $settings_shs, $bundle, $field_name);
 
     $element += [
       '#shs' => $settings_shs,
@@ -276,4 +295,32 @@ protected function settingToString($key) {
     return $options[$value];
   }
 
+  /**
+   * Returns the array of options for the widget.
+   *
+   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
+   *   The entity for which to return options.
+   *
+   * @return array
+   *   The array of options for the widget.
+   */
+  protected function getOptions(FieldableEntityInterface $entity) {
+    if (!isset($this->options)) {
+      $options = parent::getOptions($entity);
+
+      // Add a create option if the widget needs one.
+      $new_label = $this->getCreateLabel();
+      if ($new_label) {
+        $options['_create'] = $new_label;
+      }
+
+      $this->options = $options;
+    }
+    return $this->options;
+  }
+
+  public function getCreateLabel() {
+    return (string) t('Create...');
+  }
+
 }
diff --git a/modules/patched/shs.patch b/modules/patched/shs.patch
new file mode 100644
index 0000000..2900aa4
--- /dev/null
+++ b/modules/patched/shs.patch
@@ -0,0 +1,420 @@
+diff --git a/modules/contrib/shs/js/models/WidgetModel.js b/modules/contrib/shs/js/models/WidgetModel.js
+index d62b4f4..92db91c 100644
+--- a/modules/contrib/shs/js/models/WidgetModel.js
++++ b/modules/contrib/shs/js/models/WidgetModel.js
+@@ -32,6 +32,11 @@
+       defaultValue: '_none',
+ 
+       /**
++       * The new item that was created.
++       */
++      createValue: null,
++      
++      /**
+        * Position of widget in app.
+        *
+        * @type {integer}
+diff --git a/modules/contrib/shs/js/views/AppView.js b/modules/contrib/shs/js/views/AppView.js
+index 8693214..fe20ca3 100644
+--- a/modules/contrib/shs/js/views/AppView.js
++++ b/modules/contrib/shs/js/views/AppView.js
+@@ -65,9 +65,6 @@
+           parents: parents
+         }));
+       });
+-//      $.each(app.getConfig('parents'), function (index, item) {
+-//        // Add WidgetModel for each parent.
+-//      });
+ 
+       app.collection.trigger('initialize:shs');
+ 
+@@ -127,6 +124,19 @@
+           // Use value of parent widget (which is the id of the model ;)).
+           value = widgetModel.get('id');
+         }
++        else if (widgetModel.get('createValue')) {
++          // Add the created item to the original select item.
++          var options = $("option", app.$el).map(function () {
++            return $(this).val();
++          }).get();
++          if ($.inArray(value, options) === -1) {
++            var item = widgetModel.get('createValue');
++            app.$el.append($("<option/>").val(item.tid).text(item.name));
++            // We can now reset our widget model to the new tid.
++            widgetModel.set('createValue', null);
++            widgetModel.set('defaultValue', item.tid);
++          }
++        }
+       }
+       // Set the updated value.
+       app.$el.val(value).trigger({
+diff --git a/modules/contrib/shs/js/views/ContainerView.js b/modules/contrib/shs/js/views/ContainerView.js
+index ad98e3b..30b7364 100644
+--- a/modules/contrib/shs/js/views/ContainerView.js
++++ b/modules/contrib/shs/js/views/ContainerView.js
+@@ -119,7 +119,14 @@
+       container.collection.remove(models);
+ 
+       var anyValue = container.app.getSetting('anyValue');
+-      if (value !== anyValue) {
++      var createValue = container.app.getSetting('createValue');
++
++      if (value === createValue && widgetModel.get('createValue')) {
++        var item = widgetModel.get('createValue');
++        value = item.tid;
++      }
++
++      if ((value !== anyValue) && (value !== createValue)) {
+         // Add new model with current selection.
+         container.collection.add(new Drupal.shs.classes[container.app.getConfig('fieldName')].models.widget({
+           id: value,
+@@ -130,7 +137,7 @@
+         // Use value of parent widget (which is the id of the model ;)).
+         value = widgetModel.get('id');
+       }
+-
++      
+       // Update parents.
+       var parents = [];
+       var previousParent = 0;
+diff --git a/modules/contrib/shs/js/views/WidgetView.js b/modules/contrib/shs/js/views/WidgetView.js
+index 3cf9459..4bff698 100644
+--- a/modules/contrib/shs/js/views/WidgetView.js
++++ b/modules/contrib/shs/js/views/WidgetView.js
+@@ -91,6 +91,11 @@
+       // Add "any" option.
+       widget.$el.append($('<option>').text(widget.container.app.getSetting('anyLabel')).val(widget.container.app.getSetting('anyValue')));
+ 
++      // Add "create" option.
++      if (widget.container.app.getSetting('create_new_items')) {
++        widget.$el.append($('<option>').text(widget.container.app.getSetting('createLabel')).val(widget.container.app.getSetting('createValue')));
++      }
++
+       // Create options from collection.
+       widget.model.itemCollection.each(function (item) {
+         if (!item.get('tid')) {
+@@ -138,6 +143,67 @@
+         $container.append(widget.$el.fadeIn(widget.container.app.getConfig('display.animationSpeed')));
+       }
+ 
++      var createValue = widget.container.app.getSetting('createValue');
++      if (widget.$el.val() == createValue) {
++        var create_item_input_id = 'shs-widget-create-new-item-' + widget.container.app.getConfig('fieldName');
++        $container.append($('<input>')
++            .on('keyup', function(e) {
++              if (e.keyCode == 13) {
++                // Do something
++                $('#' + create_item_input_id + '_button').trigger('click');
++                e.preventDefault();
++                return false;
++              }
++            })
++            .attr('type', 'text')
++            .attr('id', create_item_input_id)
++            .attr('name', 'create_new_item')
++        ).append($('<button>')
++            .attr('id', create_item_input_id + '_button')
++            .html('Create')
++            .on('click', function(e) {
++                var value = $('#' + create_item_input_id).val();
++
++                // Get the langcode value if present.
++                var $language = $('select[name="langcode[0][value]"]');
++                var langcode = 'und';
++                if ($language) {
++                  langcode = $language.val();
++                }
++
++                $.ajax({
++                  url: widget.container.app.getConfig('createUrl'),
++                  type: 'POST',
++                  dataType: 'json',
++                  async: false,
++                  contentType: 'application/json',
++                  Accept: 'application/json',
++                  data: JSON.stringify({
++                    arguments: {
++                      value: value,
++                      bundle: widget.container.app.getConfig('bundle'),
++                      entity_id: widget.model.get('id'),
++                      langcode: langcode
++                    }
++                  })
++                }).then(function(data) {
++                  if (data !== 'null') {
++                    // Force a reload.
++                    widget.model.set('dataLoaded', false);
++
++                    // Update create value of attached model.
++                    widget.model.set('createValue', data);
++
++                    // Fire events.
++                    widget.container.collection.trigger('update:selection', widget.model, widget.model.get('defaultValue'), widget);
++                  }
++                });
++
++                e.preventDefault();
++                return false;
++            })
++        );
++      }
+       widget.model.set('dataLoaded', true);
+       // Return self for chaining.
+       return widget;
+diff --git a/modules/contrib/shs/shs.module b/modules/contrib/shs/shs.module
+index 1876d7f..eeeb0b5 100644
+--- a/modules/contrib/shs/shs.module
++++ b/modules/contrib/shs/shs.module
+@@ -79,7 +79,7 @@ function shs_term_get_parents($default_values, $settings, $target_type) {
+       $storage = Drupal::entityTypeManager()->getStorage($target_type);
+       $parent_terms = array_reverse(array_keys($storage->loadAllParents($value)));
+       $keys = array_merge([0], $parent_terms);
+-      $values = array_merge($parent_terms, [$value]);
++      $values = array_merge($parent_terms, [$settings['anyValue']]);
+       $parents[$delta] = [];
+       foreach ($keys as $index => $key) {
+         $parents[$delta][] = [
+diff --git a/modules/contrib/shs/shs.routing.yml b/modules/contrib/shs/shs.routing.yml
+index cf93fd9..f4e602e 100644
+--- a/modules/contrib/shs/shs.routing.yml
++++ b/modules/contrib/shs/shs.routing.yml
+@@ -6,3 +6,11 @@ shs.term_data:
+     entity_id: null
+   requirements:
+     _permission: 'access content'
++
++shs.create_term:
++  path: '/shs-create-term'
++  defaults:
++    _controller: '\Drupal\shs\Controller\ShsController::createTerm'
++  requirements:
++    _csrf_token: 'TRUE'
++    _custom_access:  '\Drupal\shs\Controller\ShsController::createTermAccess'
+diff --git a/modules/contrib/shs/src/Controller/ShsController.php b/modules/contrib/shs/src/Controller/ShsController.php
+index 6e4381c..f63b372 100644
+--- a/modules/contrib/shs/src/Controller/ShsController.php
++++ b/modules/contrib/shs/src/Controller/ShsController.php
+@@ -2,10 +2,16 @@
+ 
+ namespace Drupal\shs\Controller;
+ 
++use Drupal\Core\Access\AccessResult;
++use Drupal\Core\Cache\CacheableJsonResponse;
+ use Drupal\Core\Controller\ControllerBase;
++use Drupal\Core\Session\AccountInterface;
+ use Drupal\shs\Cache\ShsCacheableJsonResponse;
+ use Drupal\shs\Cache\ShsTermCacheDependency;
++use Drupal\taxonomy\Entity\Vocabulary;
+ use Symfony\Component\DependencyInjection\ContainerInterface;
++use Symfony\Component\HttpFoundation\JsonResponse;
++use Symfony\Component\HttpFoundation\Request;
+ 
+ /**
+  * Controller for getting taxonomy terms.
+@@ -80,4 +86,93 @@ public function getTermData($identifier, $bundle, $entity_id = 0) {
+     return $response;
+   }
+ 
++  /**
++   * Create term data.
++   *
++   * @param \Symfony\Component\HttpFoundation\Request $request
++   *
++   * @return JsonResponse
++   *   Json response.
++   */
++  public function createTerm(Request $request) {
++
++    $result = NULL;
++
++    // Obtain the data from the json.
++    $data = json_decode($request->getContent());
++    $value = $data->arguments->value;
++    $bundle = $data->arguments->bundle;
++    $entity_id = $data->arguments->entity_id;
++    $langcode = $data->arguments->langcode;
++
++    if (!$langcode) {
++      $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
++    }
++
++    $entity_manager = \Drupal::getContainer()->get('entity.manager');
++    $storage = $entity_manager->getStorage('taxonomy_term');
++
++    // Try to find the term.
++    $found = null;
++    $terms = $storage->loadTree($bundle, $entity_id, 1, TRUE);
++    foreach ($terms as $term) {
++      if ($term->hasTranslation($langcode)) {
++        $term = $term->getTranslation($langcode);
++      }
++      else {
++        $langcode = $term->default_langcode;
++      }
++
++      if (strcasecmp($term->getName(), $value) === 0) {
++        $found = $term;
++        break;
++      }
++    }
++
++    if (!$found) {
++      $term = $storage->create([
++        'vid' => $bundle,
++        'langcode' => $langcode,
++        'name' => $value,
++        'parent' => array($entity_id),
++      ]);
++      $term->save();
++    }
++    else {
++      $term = $found;
++    }
++
++    $result = (object) [
++      'tid' => $term->id(),
++      'name' => $term->getName(),
++      'description__value' => $term->getDescription(),
++      'langcode' => $langcode,
++      'hasChildren' => shs_term_has_children($term->id()),
++    ];
++
++    $response = new JsonResponse();
++    $response->setData($result);
++
++    return $response;
++  }
++
++  /**
++   * Checks access for a specific request.
++   *
++   * @param \Drupal\Core\Session\AccountInterface $account
++   *   Run access checks for this account.
++   *
++   * @return bool
++   */
++  public function createTermAccess(AccountInterface $account) {
++    $request = \Drupal::request();
++    $data = json_decode($request->getContent());
++    $bundle = $data->arguments->bundle;
++
++    return AccessResult::allowedIfHasPermissions($account, [
++      "edit terms in {$bundle}",
++      'administer taxonomy'
++    ], 'OR');
++  }
++
+ }
+diff --git a/modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php b/modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php
+index 223ca4a..8a90412 100644
+--- a/modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php
++++ b/modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php
+@@ -2,11 +2,14 @@
+ 
+ namespace Drupal\shs\Plugin\Field\FieldWidget;
+ 
++use Drupal;
+ use Drupal\Component\Utility\Html;
++use Drupal\Core\Entity\FieldableEntityInterface;
+ use Drupal\Core\Field\FieldDefinitionInterface;
+ use Drupal\Core\Field\FieldItemListInterface;
+ use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget;
+ use Drupal\Core\Form\FormStateInterface;
++use Drupal\Core\Render\BubbleableMetadata;
+ use Drupal\Core\Url;
+ 
+ /**
+@@ -47,7 +50,6 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
+       '#title' => t('Allow creating new items'),
+       '#default_value' => $this->getSetting('create_new_items'),
+       '#description' => t('Allow users to create new items of the source bundle.'),
+-      '#disabled' => TRUE,
+     ];
+     $element['create_new_levels'] = [
+       '#type' => 'checkbox',
+@@ -59,7 +61,6 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
+           ':input[name="fields[' . $field_name . '][settings_edit_form][settings][create_new_items]"]' => ['checked' => TRUE],
+         ],
+       ],
+-      '#disabled' => TRUE,
+     ];
+     $element['force_deepest'] = [
+       '#type' => 'checkbox',
+@@ -103,6 +104,12 @@ public function settingsSummary() {
+    * {@inheritdoc}
+    */
+   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
++
++    global $base_url;
++
++    // Don't cache because we get illegal choice errors if new items are created.
++    $form_state->disableCache();
++
+     $element = parent::formElement($items, $delta, $element, $form, $form_state);
+     if (isset($form_state->getBuildInfo()['base_form_id']) && ('field_config_form' === $form_state->getBuildInfo()['base_form_id'])) {
+       // Do not display the shs widget in the field config.
+@@ -122,6 +129,8 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
+       'anyLabel' => $this->getEmptyLabel() ?: t('- None -'),
+       'anyValue' => '_none',
+       'addNewLabel' => t('Add another item'),
++      'createValue' => '_create',
++      'createLabel' => $this->getCreateLabel() ?: t('Create...'),
+     ];
+ 
+     $bundle = reset($target_bundles);
+@@ -139,10 +148,22 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
+       $parents = shs_term_get_parents($default_value, $settings_additional, $this->fieldDefinition->getItemDefinition()->getSetting('target_type'));
+     }
+ 
++    // Generate a token for our ajax url.
++    // We need to run this through a render function because Drupal.url generates
++    // a placeholder token.
++    $urlBubbleable = Url::fromRoute('shs.create_term')->toString(TRUE);
++    $urlRender = array(
++      '#markup' => $urlBubbleable->getGeneratedUrl(),
++    );
++    BubbleableMetadata::createFromRenderArray($urlRender)
++      ->merge($urlBubbleable)->applyTo($urlRender);
++    $url = \Drupal::service('renderer')->renderPlain($urlRender);
++
+     $settings_shs = [
+       'settings' => $this->getSettings() + $settings_additional,
+       'bundle' => $bundle,
+       'baseUrl' => Url::fromUri('base:/shs-term-data')->toString(),
++      'createUrl' => $url,
+       'cardinality' => $this->fieldDefinition->getFieldStorageDefinition()->getCardinality(),
+       'parents' => $parents,
+       'defaultValue' => $default_value,
+@@ -276,4 +297,32 @@ protected function settingToString($key) {
+     return $options[$value];
+   }
+ 
++  /**
++   * Returns the array of options for the widget.
++   *
++   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
++   *   The entity for which to return options.
++   *
++   * @return array
++   *   The array of options for the widget.
++   */
++  protected function getOptions(FieldableEntityInterface $entity) {
++    if (!isset($this->options)) {
++      $options = parent::getOptions($entity);
++
++      // Add a create option if the widget needs one.
++      $new_label = $this->getCreateLabel();
++      if ($new_label) {
++        $options['_create'] = $new_label;
++      }
++
++      $this->options = $options;
++    }
++    return $this->options;
++  }
++
++  public function getCreateLabel() {
++    return (string) t('Create...');
++  }
++
+ }
