Commit 5ad05c9
authored
fix(edit-content): keep CATEGORY form value as array across workflow rebuilds (#35530)
## Parent Issue
Fixes #35529
## Proposed Changes
In the **new Edit Content experience**, after firing any workflow action
that re-fetches the contentlet (Reset Workflow, or any subaction that
updates the contentlet's `modDate`), required CATEGORY fields visually
retained their selected chips but the form control's value silently
reverted to a CSV string. The next save coerced that string to `[]` and
the backend rejected with `"field required"` for required category
fields. A secondary symptom — an Angular `"There is no FormControl
instance attached"` error during form rebind — left some sibling inputs
visually stuck in a disabled / loading state.
Two related fixes in `libs/edit-content`:
1. **`dot-edit-content-field.constant.ts`** — Add `FIELD_TYPES.CATEGORY`
to `UNCASTED_FIELD_TYPES`. `categoryResolutionFn` returns an array of
category keys, but it was being routed through
`castSingleSelectableValue` (intended for radio/select/checkbox
single-value fields), which falls into `String(value)` and produces a
CSV string. The CSV intermediate had no consumer — the store ignores the
form's initial value and reads the contentlet directly — but
`processFormValue` was silently turning the unrecovered string into
`[]`. Keeping the array shape end-to-end is also defense in depth: if
the LOADED-state effect ever fails to upgrade keys to inodes, the form
sends keys instead of an empty array.
2. **`dot-category-field.component.ts`** — Override `writeValue` to
re-emit inodes after a form rebuild. Angular's `formGroup` directive
does not destroy the `dot-category-field` on rebind — the same component
instance is reused with a new `FormControl`. The store stays in `LOADED`
state from the first mount, so the LOADED effect doesn't refire and
never pushes the inodes back into the new control. The `onChange` call
is deferred to a microtask because `writeValue` is invoked synchronously
inside `FormGroupDirective._updateDomValue → setUpControl(...)`,
**before** Angular assigns `dir.control = newCtrl`; calling `onChange`
synchronously dereferences the not-yet-assigned `dir.control` and throws
`"no FormControl instance attached"`, which aborted the rebind loop and
left sibling controls in their stale `form.disable()` state.
The constructor's `handleChangeValue($value)` was also removed — it
wired a `signalMethod` that fed `writeValue` back into the store,
duplicating what `store.load()` already does from the contentlet, and
was misnamed (`setSelectedFromInodes` was actually being called with
keys, not inodes).
## Why is this important
- Restores save functionality for any user editing content with required
CATEGORY fields after running a workflow action — currently a hard
block.
- Removes a silent "form looks fine, save fails" failure mode that's
confusing to debug.
- Eliminates a console-level Angular error that was masking the
secondary "stuck disabled inputs" issue.
## Quality Checklist
- [x] My code follows the style guidelines of this project.
- [x] I have performed a self-review of my own code.
- [x] I have made corresponding changes to the documentation. (No docs
needed)
- [x] My changes generate no new warnings.
- [x] I have added tests that prove my fix is effective. (See
verification below)
- [x] New and existing unit tests pass locally with my changes.
- [x] Any dependent changes have been merged and published.
## Additional Information
**Verified end-to-end in the new edit-content UI**, with
`dot-category-field` instances on a Job Aid Article contentlet (required
`audience` and `navigationLocation`):
| Step | Action | Result |
|---|---|---|
| 1 | Modify title + Publish | 200 OK, new inode |
| 2 | Click Reset Workflow | Form values stay as arrays of inodes; no
inputs stuck disabled |
| 3 | Modify title | OK |
| 4 | Click Publish | 200 OK, no `"field required"` error, no console
errors |
Form-control inspection after Reset Workflow:
```js
{ audience: ["ae4f244a...", "e046cc15..."],
navigationLocation: ["98114998...", "27d24583..."],
formValid: true,
cats: [{ fld: "navigationLocation", isDis: false, sigVal: ["jobAidsA","jobAidsB"] },
{ fld: "audience", isDis: false, sigVal: ["audienceA","audienceB"] }] }
```
`sigVal` is now an array of keys instead of the previous CSV string
`"jobAidsA,jobAidsB"` — confirming the cast is gone.
**Tests:** All `category` test suites pass (`yarn nx test edit-content
--testPathPattern=category` → 1809 passed). The single failing test in
the broader edit-content run (`calendar-field.util.spec.ts` — "now"
handling) is a pre-existing flake unrelated to this change.1 parent 6bebb1d commit 5ad05c9
4 files changed
Lines changed: 64 additions & 17 deletions
File tree
- core-web/libs/edit-content/src/lib
- fields/dot-edit-content-category-field
- components/dot-category-field
- utils
- models
Lines changed: 14 additions & 16 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | 1 | | |
4 | 2 | | |
5 | 3 | | |
| |||
24 | 22 | | |
25 | 23 | | |
26 | 24 | | |
| 25 | + | |
27 | 26 | | |
28 | 27 | | |
29 | 28 | | |
| |||
88 | 87 | | |
89 | 88 | | |
90 | 89 | | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | 90 | | |
97 | 91 | | |
98 | 92 | | |
99 | 93 | | |
100 | 94 | | |
101 | 95 | | |
102 | | - | |
103 | | - | |
104 | 96 | | |
105 | 97 | | |
106 | 98 | | |
| |||
144 | 136 | | |
145 | 137 | | |
146 | 138 | | |
147 | | - | |
148 | | - | |
149 | | - | |
| 139 | + | |
| 140 | + | |
150 | 141 | | |
| 142 | + | |
151 | 143 | | |
152 | 144 | | |
153 | 145 | | |
154 | | - | |
| 146 | + | |
| 147 | + | |
155 | 148 | | |
156 | 149 | | |
157 | 150 | | |
158 | | - | |
159 | | - | |
160 | | - | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
161 | 159 | | |
Lines changed: 23 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
648 | 649 | | |
649 | 650 | | |
650 | 651 | | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
651 | 674 | | |
Lines changed: 22 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
293 | 293 | | |
294 | 294 | | |
295 | 295 | | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
Lines changed: 5 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
22 | 26 | | |
23 | 27 | | |
24 | 28 | | |
| |||
0 commit comments