Overview
Quoting \Drupal\experience_builder\SdcPropToFieldTypePropMatcher::iterateJsonSchema():
…
throw new \LogicException('Support for "array" props is not yet implemented.');
…
Proposed resolution
Support it:
- at the prop expression level
- must be able to compute a
StaticPropSource - must be able to match against field instances in a
DynamicPropSource, to avoid accumulating a gap/technical debt for #3455629: [PP-1] [META] 7. Content Templates — aka "default layouts" — affects the tree+props data model - must allow existing
all-propsSDC to continue to work, and its test coverage to still pass - must come with solid test coverage, proving
type: arrayworks with both scalars (sparklineSDC) andtype: objects (image-gallerySDC)
Out-of-scope: fully working widgets for StaticPropSources — see #28 for how it for example only partially works for MediaLibraryWidget for the new image-gallery test SDC. #3517868: Add e2e tests for multi-value textfield widget in page data form might help. But #3515563: [META] Expand support to *all* SDC prop shapes, and *all* core field widgets is the one whose scope it is to get all these working.
User interface changes
sparklinetest SDC-
powered by:
props: type: object required: - data properties: data: type: array title: Sparkline data maxItems: 100 items: type: integer minimum: -100 maximum: 100 examples: - [0, 10, 20, 30, -40, -50, 5, 7, 9] image-gallerytest SDC-
powered by
props: type: object required: - images properties: caption: type: string title: Caption description: The image gallery caption images: title: 'Images for gallery' type: array items: $ref: json-schema-definitions://experience_builder.module/image # @todo `type: object` should not be necessary, it's because \Drupal\sdc\Component\ComponentValidator::getClassProps() does not yet support $ref type: object examples: - - src: gracie.jpg alt: 'A good dog' width: 601 height: 402 - src: gracie.jpg alt: 'Still a good dog' width: 601 height: 402 - src: gracie.jpg alt: 'The BEST dog!' width: 601 height: 402… with a partially working widget too, see video in #28.
| Comment | File | Size | Author |
|---|---|---|---|
| #28 | XB's first image gallery.mov | 42.88 MB | wim leers |
| #27 | preview array of images.png | 92.08 KB | wim leers |
| #27 | preview array of integers.png | 2.78 KB | wim leers |
| #16 | Screenshot 2024-09-27 at 5.10.16 PM.png | 146.38 KB | wim leers |
| #13 | Screenshot 2024-09-27 at 4.17.57 PM.png | 32.43 KB | wim leers |
Issue fork experience_builder-3467870
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
kristen polTo be clear, this is so you can have a multivalue prop? Like multiple links or tags or buttons?
Comment #3
wim leers#2: yes.
(Which is what you referred to in #3454125-70: Implement temporary design system for the DrupalCon Barcelona demo, point 3.
Comment #4
kristen polGotcha 👍 thanks for the clarification
Comment #5
wim leersComment #6
wim leersWhile this does need design, I think we can lay the shape matching foundations. A conversation with @catch about #3440578: [PP-2] JSON-based data storage proposal for component-based page building yesterday made me realize that:
type: array, items: integerandtype: array, items: string, maxItems: 2would actually help the discussion over at #3440578Comment #10
wim leersI've made progress today on updating
FieldTypePropExpression,StaticPropSourceandEvaluatorto supporttype: array.How?
By changing
StaticPropSourceto not be required to contain aFieldItemInterface(i.e. a single field delta), but instead allowing aFieldItemListInterfacetoo (i.e. multiple field deltas).It's too unorganized right now to push; expect an update tomorrow 😊
Thanks @catch for nudging me in this direction 😄
Comment #11
wim leersJust pushed initial test coverage in
PropSourceTest::testStaticPropSource(), to test it with multiple cardinality:It should now fail like this:
… because
StaticPropSourcecurrently ignores cardinality — it always just constructs a singleFieldItemInterfaceobject rather than a list when cardinality >=1.Comment #12
wim leersYay, from:
(IOW: a single integer is passed, when an array of integers is needed)
to … that test passing 🤓
More coming.
Comment #13
wim leersI was chasing a heisenbug for a few hours today. I then eventually found the root cause.
It happens only for a
list_stringfield type with one of its allowed values the empty string:… because somewhere
''gets cast toNULL😅XB's tests generate a random value to verify the static prop source works end-to-end, and due to the changes in this MR (introducing the use of



FieldItemListand hence callingFieldItemList::isEmpty(), which we didn't call before), this:now resulted in
which is obviously wrong, but
count()works fine:… this is valid configuration for the
list_stringfield type: its config schema typefield.storage_settings.list_stringdoes not forbid this.But the UI does forbid it:


which causes:
So probably a fixed
ListStringItem::isEmpty()that is more strict than the inherited\Drupal\options\Plugin\Field\FieldType\ListItemBase::isEmpty()'s implementation:… would not even be accepted by Drupal core maintainers! 😬
Unfortunately, I lost hours today because of this. If there was config schema validation in place, this would've been sorted out in minutes. 😭
So: not filing a Drupal core issue,
but I am creating one for Experience Builder to disallow← I can't justify that, because it's a valid use case for SDC, and we can make it work.''as anenumvalue, so that'd be a reason to refuse to support such an SDCComment #14
wim leersTo make #13 discoverable.
Comment #15
wim leersI actually think that matching field instances should be possible too, so broadening the issue title/scope 🤓
Comment #16
wim leerstype: arraybreakthrough — it’s starting to work end-to-end! 😄Soon: 🖼️🖼️🖼️🖼️ aka image galleries!
(Note that this currently requires removing the logic in
\Drupal\experience_builder\Controller\SdcController::getComponentsList()to determine thedynamic_prop_source_candidatesfor each SDC.)Comment #17
wim leers99% of remaining test failures are due to not yet supporting finding
DynamicPropSources (aka existing entity field instances) for thetype: arrayprop shape.That's why I widened the scope in #15 — because I first thought it'd be an order of magnitude harder than supporting
StaticPropSources (which is the only thing the XB UI currently supports). But it'd be a shame to let that part "fall behind", so trying to tackle this while my head is in this space 😊Comment #18
wim leers1% of remaining test failures are in the Cypress E2E tests, which makes sense: the Redux integration has only been built with single-cardinality props in mind, that's changing here.
IOW: having this in also empowers #3463842: [META] Redux sync on ALL prop types, not just ones with a single [value] property to design a more complete solution.
Comment #19
wim leersMerged in all upstream changes.
We may also need to consider this in #3467954: META: Evolve XB UI's data model to allow non-SDC components' inputs, DynamicPropSource support, etc..
Comment #20
tedbowgoing to review
Comment #21
tedbow@Wim Leers the direction looks good to me!
Comment #22
wim leershttps://nerdy.dev/carousel-adaptive-anchor-positioning-with-calc-in-a-co... would be a fantastic way to demonstrate this!
Comment #23
wim leersComment #24
wim leersComment #25
geek-merlin@wim: Can you clarify: Is "array" a dict, a list, or any of it? PHP lenience...
Comment #26
wim leers~90% done now. To be continued tomorrow.
Comment #27
wim leersGood news — previews are now working! For example, for the test SDC:

powered by:
And, the one everyone has been waiting for: image galleries … found and fixed a pre-existing bug thanks to this work: #3522673: Previews of SDCs with default image props broken. With it, I get:
powered by
Comment #28
wim leers— me in #16, ~7 months ago
Here we go! 🚀
(It doesn't work completely yet — only the first selected image media item is rendered due to the
mediaSelectionclient-side transform, and removing the last selected media item also doesn't work yet. But those are out-of-scope to tackle here.)Comment #29
wim leersRemoving the , because extracted the relevant part into a new issue: #3522718: [later phase] [needs design] UX for associating mismatched cardinality field instance (too little or too much) with a higher cardinality SDC prop (e.g. `type: array, maxItems: 5`) or lower cardinality (e.g. `type: string`).
This MR removes 3
@todos from the codebase, all new@todos are for existing issues.Self-RTBC'ing because @tedbow already approved the direction in #21. I've applied thorough self-review. And I desperately need this to make progress on #3520449: [META] Production-ready data storage! 😅 Even if imperfect (which it surely will prove to be), this represents a big step forward, one we've been postponing for far too long.
Comment #31
wim leersComment #33
larowlanFYI this no longer works anymore.
There was no e2e tests added here and in manual testing:
* sparkline never shows the edit form, it just spins
* image gallery will render with the 3 example values, but as soon as you edit it, it will only ever show the first item selected (even if there are multiple images selected)
Testing with a simple multi-value string shows the same result, only ever the first value is saved.
Comment #34
larowlanAdded #3546869: Editing support for `type: array`: support multiple-cardinality Field Widgets (`StaticPropSource`s)
Comment #35
wim leerse2e tests were intentionally out of scope, this was purely about shape matching infra. The field widget/editing part of this never worked, see #16.
Correct, that's why I wrote this in #28:
That's why I posted a comment on #3463842 — see #3463842-12: [META] Redux sync on ALL prop types, not just ones with a single [value] property. But thanks for creating #3546869: Editing support for `type: array`: support multiple-cardinality Field Widgets (`StaticPropSource`s) to get that done sooner! 🤩
Comment #36
tedbowSwitching the project because I was searching for this issue and couldn't find it.