Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
diff --git a/docroot/core/config/schema/core.data_types.schema.yml b/docroot/core/config/schema/core.data_types.schema.yml
index 73db361..c6e4f8c 100644
--- a/docroot/core/config/schema/core.data_types.schema.yml
+++ b/docroot/core/config/schema/core.data_types.schema.yml
@@ -392,6 +392,9 @@ field_config_base:
required:
type: boolean
label: 'Required field'
+ orderable:
+ type: boolean
+ label: 'Orderable'
translatable:
type: boolean
label: 'Translatable'
diff --git a/docroot/core/includes/theme.inc b/docroot/core/includes/theme.inc
index 9b89250..6ddbba1 100644
--- a/docroot/core/includes/theme.inc
+++ b/docroot/core/includes/theme.inc
@@ -1682,6 +1682,66 @@ function template_preprocess_field_multiple_value_form(&$variables) {
}
/**
+ * Prepares variables for individual form element templates.
+ *
+ * Default template: field-multiple-value-without-order-form.html.twig.
+ *
+ * Combines multiple values.
+ *
+ * @param array $variables
+ * An associative array containing:
+ * - element: A render element representing the form element.
+ */
+function template_preprocess_field_multiple_value_without_order_form(&$variables) {
+ $element = $variables['element'];
+ $variables['multiple'] = $element['#cardinality_multiple'];
+
+ if ($variables['multiple']) {
+ $items = [];
+ $variables['button'] = [];
+ foreach (Element::children($element) as $key) {
+ if ($key === 'add_more') {
+ $variables['button'] = &$element[$key];
+ }
+ else {
+ $items[$key] = &$element[$key];
+ if (isset($items[$key]['_weight'])) {
+ $items[$key]['_weight']['#access'] = FALSE;
+ }
+ }
+ }
+ usort($items, '_field_multiple_value_form_sort_helper');
+
+ $variables['title'] = [];
+ if (!empty($element['#title'])) {
+ $variables['title'] = [
+ '#type' => 'label',
+ '#title' => $element['#title'],
+ '#required' => !empty($element['#required']) ? $element['#required'] : FALSE,
+ '#title_display' => 'before',
+ ];
+ }
+ $variables['items'] = $items;
+
+ if (!empty($element['#description'])) {
+ $description_id = $element['#attributes']['aria-describedby'];
+ $description_attributes['id'] = $description_id;
+ $variables['description']['attributes'] = new Attribute($description_attributes);
+ $variables['description']['content'] = $element['#description'];
+
+ // Add the description's id to the table aria attributes.
+ $variables['table']['#attributes']['aria-describedby'] = $element['#attributes']['aria-describedby'];
+ }
+ }
+ else {
+ $variables['elements'] = [];
+ foreach (Element::children($element) as $key) {
+ $variables['elements'][] = $element[$key];
+ }
+ }
+}
+
+/**
* Prepares variables for breadcrumb templates.
*
* Default template: breadcrumb.html.twig.
@@ -1861,5 +1921,8 @@ function drupal_common_theme() {
'field_multiple_value_form' => array(
'render element' => 'element',
),
+ 'field_multiple_value_without_order_form' => array(
+ 'render element' => 'element',
+ ),
);
}
diff --git a/docroot/core/lib/Drupal/Core/Field/BaseFieldDefinition.php b/docroot/core/lib/Drupal/Core/Field/BaseFieldDefinition.php
index 594f31d..aadaefe 100644
--- a/docroot/core/lib/Drupal/Core/Field/BaseFieldDefinition.php
+++ b/docroot/core/lib/Drupal/Core/Field/BaseFieldDefinition.php
@@ -233,6 +233,27 @@ public function setTranslatable($translatable) {
/**
* {@inheritdoc}
*/
+ public function isOrderable() {
+ return !empty($this->definition['orderable']);
+ }
+
+ /**
+ * Sets whether the field is orderable.
+ *
+ * @param bool $orderable
+ * Whether the field is orderable.
+ *
+ * @return $this
+ * The object itself for chaining.
+ */
+ public function setOrderable($orderable) {
+ $this->definition['orderable'] = $orderable;
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function isRevisionable() {
return !empty($this->definition['revisionable']);
}
diff --git a/docroot/core/lib/Drupal/Core/Field/FieldConfigBase.php b/docroot/core/lib/Drupal/Core/Field/FieldConfigBase.php
index d7ddd18..5f80f9b 100644
--- a/docroot/core/lib/Drupal/Core/Field/FieldConfigBase.php
+++ b/docroot/core/lib/Drupal/Core/Field/FieldConfigBase.php
@@ -103,6 +103,15 @@
protected $required = FALSE;
/**
+ * Flag indicating whether the field is orderable.
+ *
+ * Defaults to TRUE.
+ *
+ * @var bool
+ */
+ protected $orderable = TRUE;
+
+ /**
* Flag indicating whether the field is translatable.
*
* Defaults to TRUE.
@@ -332,6 +341,23 @@ public function setTranslatable($translatable) {
/**
* {@inheritdoc}
*/
+ public function isOrderable() {
+ // Make the default state TRUE even when the cardinality doesn't allow
+ // multiple values.
+ return $this->orderable || $this->getFieldStorageDefinition()->getCardinality() == 1;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setOrderable($orderable) {
+ $this->orderable = $orderable;
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function getSettings() {
return $this->settings + $this->getFieldStorageDefinition()->getSettings();
}
diff --git a/docroot/core/lib/Drupal/Core/Field/FieldConfigInterface.php b/docroot/core/lib/Drupal/Core/Field/FieldConfigInterface.php
index d8b055a..e9dc4ce 100644
--- a/docroot/core/lib/Drupal/Core/Field/FieldConfigInterface.php
+++ b/docroot/core/lib/Drupal/Core/Field/FieldConfigInterface.php
@@ -50,6 +50,16 @@ public function setDescription($description);
public function setTranslatable($translatable);
/**
+ * Sets whether the field is orderable.
+ *
+ * @param bool $orderable
+ * Whether the field is orderable.
+ *
+ * @return $this
+ */
+ public function setOrderable($orderable);
+
+ /**
* Sets field settings.
*
* Note that the method does not unset existing settings not specified in the
diff --git a/docroot/core/lib/Drupal/Core/Field/WidgetBase.php b/docroot/core/lib/Drupal/Core/Field/WidgetBase.php
index 3d0db4c..b7ca726 100644
--- a/docroot/core/lib/Drupal/Core/Field/WidgetBase.php
+++ b/docroot/core/lib/Drupal/Core/Field/WidgetBase.php
@@ -210,7 +210,7 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
if ($elements) {
$elements += array(
- '#theme' => 'field_multiple_value_form',
+ '#theme' => $this->fieldDefinition->isOrderable() ? 'field_multiple_value_form' : 'field_multiple_value_without_order_form',
'#field_name' => $field_name,
'#cardinality' => $cardinality,
'#cardinality_multiple' => $this->fieldDefinition->getFieldStorageDefinition()->isMultiple(),
diff --git a/docroot/core/modules/block_content/config/install/field.storage.block_content.body.yml b/docroot/core/modules/block_content/config/install/field.storage.block_content.body.yml
index f7c504d..2a73f84 100644
--- a/docroot/core/modules/block_content/config/install/field.storage.block_content.body.yml
+++ b/docroot/core/modules/block_content/config/install/field.storage.block_content.body.yml
@@ -12,6 +12,7 @@ settings: { }
module: text
locked: false
cardinality: 1
+orderable: true
translatable: true
indexes: { }
persist_with_no_fields: true
diff --git a/docroot/core/modules/field_ui/src/Form/FieldConfigEditForm.php b/docroot/core/modules/field_ui/src/Form/FieldConfigEditForm.php
index ff6d157..1e817c9 100644
--- a/docroot/core/modules/field_ui/src/Form/FieldConfigEditForm.php
+++ b/docroot/core/modules/field_ui/src/Form/FieldConfigEditForm.php
@@ -71,6 +71,16 @@ public function form(array $form, FormStateInterface $form_state) {
'#weight' => -5,
);
+ if ($this->entity->getFieldStorageDefinition()->getCardinality() != 1) {
+ $form['orderable'] = [
+ '#type' => 'checkbox',
+ '#title' => $this->t('Orderable'),
+ '#default_value' => $this->entity->isOrderable(),
+ '#weight' => -5,
+ '#description' => t('Orderable multiple fields widgets are in a table with drag and drop.'),
+ ];
+ }
+
// Create an arbitrary entity object (used by the 'default value' widget).
$ids = (object) array(
'entity_type' => $this->entity->getTargetEntityTypeId(),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.