Problem/Motivation

Multivalue fields are currently very difficult to manage, especially when there are many values to maintain:

Canvas entity reference multivalue field with a comma seperated autocomplete

With the current solution (comma-separated input of values), the flyout doesn't make sense to me.

Proposed resolution

If the values were in separate fields, it would be a different story, of course. Then the flyout would save a lot of space in the sidebar:

Canvas entity reference multivalue field with singular autocomplete fields for each value
Of course, this needs delete buttons for the individual values, and ideally, drag handles to adjust the sort order.

Another, possibly simpler, solution would be to remove the flyout and simply display the comma-separated field directly. That would at least be a little less fiddly.

I can think of a lot of possibilities, but of course it has to be feasible, and it probably shouldn't stray too far from the standard Canvas Core solutions.

Remaining tasks

User interface changes

API changes

Data model changes

Comments

thomas.frobieter created an issue. See original summary.

thomas.frobieter’s picture

Issue summary: View changes

  • zeeshan_khan committed f52f055d on issue/3608101-individual-rows-multivalue-ux
    Issue #3608101: Fix no-bitwise ESLint errors in crypto.randomUUID...

  • zeeshan_khan committed 2ce7265d on 1.0.x
    Issue #3608101: Render multi-value entity reference props as individual...
zeeshan_khan’s picture

Status: Active » Needs review

MR - https://git.drupalcode.org/project/canvas_entity_reference/-/merge_reque...
I have added a proper UI fix and its merged into dev branch @thomas.frobieter - if you can give it a test will be great.

Thanks

thomas.frobieter’s picture

Status: Needs review » Needs work

Aww, thats great @zeeshan_khan!

The only issue I've found so far is that the maximum number of items is exceeded by one.
For example: If five items are configured, it's possible to reference six. After selecting a different canvas block and then re-selecting the new one, the sixth value disappeared. However, I am able to select the sixth item again. After selecting the sixth item, the Add button becomes disabled.

Not a big deal, but yeah..

    tags:
      type: array
      title: Multi-value with maxItems
      maxItems: 5
      items:
        type: ["string", "null"]
        x-entity-type: taxonomy_term
zeeshan_khan’s picture

Status: Needs work » Needs review
StatusFileSize
new181.26 KB

Thanks for the quick review @thomas.frobieter

MR - https://git.drupalcode.org/project/canvas_entity_reference/-/merge_reque... Fixes the issue
fix issue

brunoalmeida’s picture

#5 MR works great!
+1

drale01’s picture

Status: Needs review » Needs work

Tested on 1.0.x-dev after the individual-row UX (#5 / merged work).

The new per-delta autocomplete rows are a big UX improvement — add/remove works well.

One remaining gap from the proposed resolution: manual sorting / drag handles still don’t work for multi-value entity reference props. Canvas Core already supports reorder for other unlimited multi-value fields, but with entity_reference_autocomplete_multi the order can’t be changed (or doesn’t persist).

  • zeeshan_khan committed 49f2d7df on issue/3608101-drag-to-reorder
    Issue #3608101: Sync preview after tabledrag via post-render change...

  • zeeshan_khan committed 493ef464 on issue/3608101-drag-to-reorder
    Issue #3608101: Use MutationObserver to detect drag end, not...

  • zeeshan_khan committed d71c318f on issue/3608101-drag-to-reorder
    Issue #3608101: Fix drag-to-reorder for multi-value entity reference...

  • zeeshan_khan committed 890c4884 on issue/3608101-drag-to-reorder
    Issue #3608101: Fix drag-to-reorder for multi-value entity reference...

  • zeeshan_khan committed 73f82954 on issue/3608101-drag-to-reorder
    Issue #3608101: Fix ESLint errors in entity-reference-autocomplete-...

  • zeeshan_khan committed c4cc4b8a on 1.0.x
    Issue #3608101: Sort entity reference records by _weight after tabledrag
    
zeeshan_khan’s picture

Status: Needs work » Needs review

@drale01 - Thanks for pointing that out!
MR !20 Fixes the issue.
1.0.x-dev - is ready for testing again

Three fixes are included:

1. Transform ignored _weight order after drag. Canvas's formStateToObject() via qs promotes numeric-keyed objects to JavaScript arrays, so the value arrives in the transform already as an array. The original code returned arrays as-is without sorting. Added a sortByWeight() helper (mirrors normalizeMultipleRecords() in Canvas Core's transforms.ts) and applied it in both the array and object code paths of toRecordsArray().
2. Live preview stale after drag — debounce/closure timing. Tabledrag assigns _weight values synchronously before React re-renders. Each assignment fires stableOnChange, which calls updateStore with latestPropsRef.current.formState — still the pre-drag state. Each ComponentFormField has its own independent 400ms debounce, so stale calls from every weight field survive independently and fire with wrong merged state on subsequent drags, corrupting the preview. A MutationObserver on the table detects drag end via the removal of the drag CSS class (triggered by tabledrag's dropRow()). A setTimeout(0) defers until React flushes all batched updates. A fresh native change event is then dispatched on every _weight select in the table, resetting all debounce timers so all stale calls are cancelled and the fresh calls fire with the correct post-drag state.
3. Drupal core tabledrag crash on AJAX rebuild. When changedRowIds from a previous tabledrag instance holds stale row IDs after an AJAX table rebuild, new self.row(null, ...) leaves this.table undefined and markChanged() crashes. Fixed via an IIFE guard patched onto Drupal.tableDrag.prototype.row.prototype.markChanged at module load time.
4. maxItems maps to field cardinality for per-delta widget. The per-delta widget always used CARDINALITY_UNLIMITED, so Drupal rendered one extra empty row beyond maxItems and the Canvas + Add button stayed enabled one step too long. Cardinality is now set to maxItems when present.