Skip to content

fix: CXSPA-13057: deactivated "Add" buttons in product-card after no-attribute-change roundtrip#21727

Open
Uli-Tiger wants to merge 4 commits into
developfrom
feature/CXSPA-13057
Open

fix: CXSPA-13057: deactivated "Add" buttons in product-card after no-attribute-change roundtrip#21727
Uli-Tiger wants to merge 4 commits into
developfrom
feature/CXSPA-13057

Conversation

@Uli-Tiger

@Uli-Tiger Uli-Tiger commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary
Fixed the CPQ V2 bug where product-card action buttons (Add/Select/Deselect) stayed disabled after a round trip that produced no attribute changes.

Root cause
The component-level loading$ flag was set to true on user action but only ever reset to false when the attribute component was destroyed and re-created. That re-creation is gated by a deep-equality check in configurator-attribute-composition.directive.ts. With CPQ V2, a no-change round trip returns identical attribute data, so the component is not re-created and loading$ stays true forever.

Changes
Base components (multi-selection-base, single-selection-base): subscribe to configuratorCommonsService.isConfigurationLoading(owner) and reset loading$ to false when the round trip completes (the store loading flag resets regardless of whether content changed). Added Subscription + ngOnDestroy cleanup.

Product card (.ts / .html): introduced disableActions$ (local product-fetch loading OR parent loading$), bound the three action buttons and the quantity control to it, and removed the loading$.next(true) calls from the action handlers so the local flag is no longer left stuck. Immediate feedback is preserved because the parent sets its loading$ synchronously via the emitted event.

Tests: added mocks/isConfigurationLoading and new specs covering loading reset and button re-enable after a no-change round trip; added fixture teardown to the three real-store specs to avoid leaked store subscriptions (repo uses destroyAfterEach: false).

side-Issue discovered (caused type error in second roundtrip): In configurator-attribute-multi-selection-bundle.component.ts I made both helpers immutable — they build a new array (and a new value object for the changed value) instead of mutating in place:

updateMultipleSelectionValues now uses this.multipleSelectionValues.map(...). updateMultipleSelectionValuesQuantity now creates an updatedValue copy instead of value.quantity = ….

…attribute-change roundtrip

Summary
Fixed the CPQ V2 bug where product-card action buttons (Add/Select/Deselect) stayed disabled after a round trip that produced no attribute changes.

Root cause
The component-level loading$ flag was set to true on user action but only ever reset to false when the attribute component was destroyed and re-created. That re-creation is gated by a deep-equality check in configurator-attribute-composition.directive.ts. With CPQ V2, a no-change round trip returns identical attribute data, so the component is not re-created and loading$ stays true forever.

Changes
Base components (multi-selection-base, single-selection-base): subscribe to configuratorCommonsService.isConfigurationLoading(owner) and reset loading$ to false when the round trip completes (the store loading flag resets regardless of whether content changed). Added Subscription + ngOnDestroy cleanup.

Product card (.ts / .html): introduced disableActions$ (local product-fetch loading OR parent loading$), bound the three action buttons and the quantity control to it, and removed the loading$.next(true) calls from the action handlers so the local flag is no longer left stuck. Immediate feedback is preserved because the parent sets its loading$ synchronously via the emitted event.

Tests: added mocks/isConfigurationLoading and new specs covering loading reset and button re-enable after a no-change round trip; added fixture teardown to the three real-store specs to avoid leaked store subscriptions (repo uses destroyAfterEach: false).

side-Issue discovered (cause type error in second roundtrip):
In configurator-attribute-multi-selection-bundle.component.ts I made both helpers immutable — they build a new array (and a new value object for the changed value) instead of mutating in place:

updateMultipleSelectionValues now uses this.multipleSelectionValues.map(...).
updateMultipleSelectionValuesQuantity now creates an updatedValue copy instead of value.quantity = ….
@Uli-Tiger Uli-Tiger requested review from a team as code owners July 10, 2026 13:50
@github-actions github-actions Bot marked this pull request as draft July 10, 2026 13:50
@Uli-Tiger Uli-Tiger marked this pull request as ready for review July 10, 2026 13:52
@github-actions

Copy link
Copy Markdown
Contributor

Merge Checks Failed

Please push a commit to re-trigger the build.
To push an empty commit you can use `git commit --allow-empty -m "Trigger Build"`

@github-actions github-actions Bot marked this pull request as draft July 10, 2026 14:09
@Uli-Tiger Uli-Tiger marked this pull request as ready for review July 10, 2026 14:18
@cypress

cypress Bot commented Jul 10, 2026

Copy link
Copy Markdown

spartacus    Run #54000

Run Properties:  status check passed Passed #54000  •  git commit 23b3fc4b21 ℹ️: Merge 0c09e88bf7594dbbd31b907eda716a89c63d642f into d19891117fa09bcc34ac487d7eef...
Project spartacus
Branch Review feature/CXSPA-13057
Run status status check passed Passed #54000
Run duration 04m 18s
Commit git commit 23b3fc4b21 ℹ️: Merge 0c09e88bf7594dbbd31b907eda716a89c63d642f into d19891117fa09bcc34ac487d7eef...
Committer Ulrich Stellmacher
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 3
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 103
View all changes introduced in this branch ↗︎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant