You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In the templates portlet (/templates/edit/...), removing a row from a multi-row layout causes columns within other rows to reorder (boxes "pushed up" to the left) and, in some scenarios, rows to appear duplicated. The bug does not affect the EMA layout editor — only the standalone templates portlet.
This regressed when @for row tracking in template-builder.component.html switched from identify(row) (id+index) to row.id directly (commit ab89c85, PR #35277). Previously the index-shift on deletion forced Angular to destroy/recreate every subsequent row, which incidentally reset GridStack state and masked a latent state-corruption bug in updateOldRows.
Root cause (technical)
The templates portlet wrapper (dot-template-builder.component.ts) called updateTemplate.emit(item) synchronously on every templateChange. That propagates through the parent store's working signal and echoes back into the designer's [layout] input → ngOnChanges → updateOldRows. After removeRow, state has gaps in y (e.g. [0, 2]) while the parsed newRows from the echoed body has sequential y ([0, 1]). updateOldRows matched by y and silently produced rows with children: undefined and missing x/y/w/h, manifesting as the visual corruption.
EMA does not have this problem because its layout signal only updates after a successful save (pageReload), so there is no synchronous echo.
Steps to Reproduce
Video screencast:
Screen.Recording.2026-05-13.at.5.15.00.PM.mov
Open a template via /templates/edit/<identifier> (design type).
Add ≥ 3 rows with multiple columns each, including columns at non-zero x positions (e.g. a box at x=6).
Delete a row from the middle of the layout.
Observe: columns within other rows visually shift / reorder, or a row appears duplicated.
Acceptance Criteria
Deleting a row in the templates portlet removes only that row.
Columns in other rows retain their positions.
No duplicated rows in the DOM after deletion.
Auto-save still fires after the 5s debounce window.
Page-leave guard still prompts when there are unsaved changes.
EMA layout editor behavior unchanged.
Regression test in place to prevent re-introduction.
Problem Statement
In the templates portlet (
/templates/edit/...), removing a row from a multi-row layout causes columns within other rows to reorder (boxes "pushed up" to the left) and, in some scenarios, rows to appear duplicated. The bug does not affect the EMA layout editor — only the standalone templates portlet.This regressed when
@forrow tracking intemplate-builder.component.htmlswitched fromidentify(row)(id+index) torow.iddirectly (commit ab89c85, PR #35277). Previously the index-shift on deletion forced Angular to destroy/recreate every subsequent row, which incidentally reset GridStack state and masked a latent state-corruption bug inupdateOldRows.Root cause (technical)
The templates portlet wrapper (
dot-template-builder.component.ts) calledupdateTemplate.emit(item)synchronously on everytemplateChange. That propagates through the parent store'sworkingsignal and echoes back into the designer's[layout]input →ngOnChanges→updateOldRows. AfterremoveRow, state has gaps iny(e.g.[0, 2]) while the parsednewRowsfrom the echoed body has sequentialy([0, 1]).updateOldRowsmatched byyand silently produced rows withchildren: undefinedand missingx/y/w/h, manifesting as the visual corruption.EMA does not have this problem because its layout signal only updates after a successful save (
pageReload), so there is no synchronous echo.Steps to Reproduce
Video screencast:
Screen.Recording.2026-05-13.at.5.15.00.PM.mov
/templates/edit/<identifier>(design type).Acceptance Criteria
dotCMS Version
main(current).Severity
Medium - Some functionality impacted
Links