Nested paragraphs with same field name are ordered wrong

Created on 5 December 2019, over 4 years ago
Updated 24 April 2023, about 1 year ago

Problem/Motivation

Using nested paragraphs we ran into the the issue that the weights were calculated wrong, after drag and dropping a paragraph that contained other paragraphs. What was wrong about the weights was, that they had the same values.
This occurred because of
first, how the updateField behavior in tabledrag.js is handling ordering, assigning the max value when running out of values

        case 'order':
          {
            var siblings = this.rowObject.findSiblings(rowSettings);
            if ($(targetElement).is('select')) {
              var values = [];
              $(targetElement).find('option').each(function () {
                values.push(this.value);
              });
              // only takes into account the values count on one level
              var maxVal = values[values.length - 1];
              
              // targetClass is field_name-delta-order and this function takes into account all values on every level
              $(siblings).find(targetClass).each(function () {
                if (values.length > 0) {
                  this.value = values.shift();
                } else {
                  this.value = maxVal;
                }
              });

and second, of how the order class is set in theme.inc inside the template_preprocess_field_multiple_value_form function

function template_preprocess_field_multiple_value_form(&$variables) {
  $element = $variables['element'];
  $variables['multiple'] = $element['#cardinality_multiple'];
  $variables['attributes'] = $element['#attributes'];

  if ($variables['multiple']) {
    $table_id = Html::getUniqueId($element['#field_name'] . '_values');
    // setting it up like doesn't take into account that multiple values on the same content could have the same field name
    $order_class = $element['#field_name'] . '-delta-order';

this leaves room for same name order errors, because we choose a popular name like 'field_body' for a paragraph field that contained other paragraphs.

Proposed resolution

Assigning a unique name to the order class using the unique table id instead of the field_name only, like

  if ($variables['multiple']) {
    $table_id = Html::getUniqueId($element['#field_name'] . '_values');
    $order_class = table_id . '-delta-order';

The reason behind this approach is that the table id already contains the field_name and also adds a unique part if the content is already on the view.

Remaining tasks

Is this a good approach or have I missed something similar in the issue queue?

🐛 Bug report
Status

Needs work

Version

9.5

Component
Theme 

Last updated about 2 hours ago

Created by

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.69.0 2024