Skip to content

Added Table component support in Core Components #1879

Open
armaang1729 wants to merge 60 commits into
devfrom
tableComponentFirstCheckIn
Open

Added Table component support in Core Components #1879
armaang1729 wants to merge 60 commits into
devfrom
tableComponentFirstCheckIn

Conversation

@armaang1729

Copy link
Copy Markdown
Collaborator

Description

Related Issue

Motivation and Context

How Has This Been Tested?

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have signed the Adobe Open Source CLA.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes and the overall coverage did not decrease.
  • All unit tests pass on CircleCi.
  • I ran all tests locally and they pass.

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

1 similar comment
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

@codecov

codecov Bot commented May 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.59459% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
.../components/internal/models/v1/form/TableImpl.java 93.93% 0 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

'checkbox-group': fieldTypes.SELECT,
'checkbox': fieldTypes.CHECKBOX,
'date-input': fieldTypes.TEXT,
'datetime-input': fieldTypes.TEXT,

@armaang1729 armaang1729 May 19, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

Previously, the replace dialog restricted targets to the same typeMap family (e.g. text-input could only be replaced with TEXT-family components). This was too limiting inside table row cells where any policy-allowed component should be swappable.

Changes:

  • isUnderCoreTableRow: detects when the editable is inside a table row/header and skips the type-family check entirely for those cells.
  • buildAllowedTemplatePathSet: still enforces the parent container's policy, so only components the row actually allows appear in the list.
  • getTemplateFieldType + null guard: fixes a crash when a component's .json omits fieldType — now falls back to model.json.
  • Added datetime-input and multiline-input to typeMap so they match correctly in standard (non-table) replace flows.

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

1 similar comment
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

@@ -0,0 +1,1108 @@
/*******************************************************************************

@armaang1729 armaang1729 May 19, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

Author-side editor hook for the core table component. Powers all structural editing actions on a table in the AEM page editor — add/delete/reorder rows, add/delete columns, and merge/split cells — by making Sling POST requests to manipulate JCR nodes directly and refreshing the table editable. Also patches the AEM overlay renderer to correctly position edit overlays on <tr> elements, which can get misplaced due to browser foster-parenting of table markup.


/**
* Table row cells must not expose the standard Delete action (row/column flows handle structure).
* @param {Granite.author.Editable} editable

@armaang1729 armaang1729 May 19, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

Table row cells must not expose the standard Delete action like normal components. The rows must be deleted through the delete row option added in the edit config of the table row.

@github-actions github-actions Bot force-pushed the tableComponentFirstCheckIn branch from 552a08c to e878597 Compare May 19, 2026 10:37
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

1 similar comment
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

@@ -0,0 +1,233 @@
/*******************************************************************************

@armaang1729 armaang1729 May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

tableview.js — purpose

This file is the runtime view for the Adaptive Form Table component. It has three responsibilities:

  1. Row insertion () — inserts a cloned <tr> into the correct <tbody> position using the row model's index. Handles three cases: empty tbody (append), index 0 (prepend before the first sibling), and mid-list (insert after the preceding sibling resolved by model index).

  2. Hook attribute patching (#syncTableRowHooks) — FormView.Utils.updateId patches element id attributes on cloned nodes but does not touch data-cmp-hook-* attributes. Without this step, cloned add/remove buttons retain the template row's stale ID, causing every dynamically-added row to dispatch the wrong model index. This method re-stamps data-cmp-hook-add-instance and data-cmp-hook-remove-instance with the newly assigned model ID immediately after insertion.

  3. min/maxOccur enforcement (#syncTableRowRepeatableControls) — after every addition or removal, walks every live row and sets data-cmp-visible on its add and remove buttons according to the instance manager's current item count vs. minOccur/maxOccur. A maxOccur of -1 means unbounded; minOccur of -1 means no floor.

handler="CQ.FormsCoreComponents.editorhooks.viewQualifiedName"
icon="viewSOMExpression"
text="View Qualified Name"/>
<addcolumn

@armaang1729 armaang1729 May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

Added addColumn and deleteColumn option in the text editconfig as the option to add column and delete will be displayed when the column cell is clicked which will be a text component so added a condition isCoreTableHeaderCell(editable) to display this option.

armaang1729

This comment was marked as resolved.

* @returns {HTMLElement}
*/
getRepeatableDomWrapper() {
const parent = this.element.parentElement;

@armaang1729 armaang1729 May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

This is the consumer of the virtual hook defined in FormPanel. The check for bemBlock on parentElement handles the edit-mode case where Sling wraps the <tr> in a <div class="cmp-adaptiveform-tablerow"> for the authoring overlay. In publish mode the <tr> has no such wrapper, so this.element (the <tr> itself) is returned directly. InstanceManager uses this for both cloning the template and tearing down removed rows.

* @returns {HTMLElement}
*/
getRepeatableInstancesContainerElement() {
const tableBody = this.element.closest(".cmp-adaptiveform-table__body") ||

@armaang1729 armaang1729 May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

Returns <tbody> as the container so InstanceManager.handleAddition inserts cloned rows into the right parent. Using closest handles both the semantic <tbody class="cmp-adaptiveform-table__body"> and any fallback structure, with parentElement as a last resort to stay consistent with the base class default.

* @param {Object} label - The label state object.
*/
updateLabel(label) {
// Table rows don't have visible labels, so this is a no-op

@armaang1729 armaang1729 May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

No-op intentionally — table rows have no visible label of their own (column headers are owned by tableheader). Without this override, applyState would call the base class updateLabel which would try to update a non-existent label DOM element.

* @param {Object} state - The state to be applied.
*/
applyState(state) {
this.updateVisible(state.visible);

@armaang1729 armaang1729 May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

Matches the FormPanel.applyState signature but explicitly skips anything table-row-irrelevant (e.g. updateLabel is a no-op here). Calling initializeHelpContent is kept because a row's visibility/enabled state still drives data-cmp-visible / data-cmp-enabled attributes that the rules engine reads.

}

FormView.Utils.setupField(({element, formContainer}) => {
return new TableRow({element, formContainer})

@armaang1729 armaang1729 May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

Registers TableRow as the view for all elements matching [data-cmp-is="adaptiveFormTableRow"]. This is the standard FormView.Utils.setupField pattern — it both creates the view for elements already in the DOM and wires up the mutation observer so dynamically added rows (repeat add) are initialized automatically.

checkLabelText(textinputid11, panelid11, 'Text Input2', 'Panel2');
// find Panel[1]'s remove button by its model index
const removeBtn1 = Object.values(formContainer._fields).find(f =>
f.getModel &&

@armaang1729 armaang1729 May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

Previous code used a hardcoded _fields array index to find the remove button, which broke after the instance removal logic was changed to id-based lookup (the field map order is no longer guaranteed to match insertion order). This change finds the remove button by inspecting the model — specifically the parent panel's index === 1 — making the test resilient to field map reordering.

cy.get(`#${removeBtn1.getId()}`).find("button").click().then(() => {
// after Panel[1] removed, find the surviving panel at index 1 by model
const panel1remaining = Object.values(formContainer._fields).find(f =>
f.getModel &&

@armaang1729 armaang1729 May 20, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE :

After removal, the surviving panel at model index === 1 and its child text input are located dynamically rather than by a fixed _fields position. This is necessary because #removeChildInstance now splices by the live array index, which can shift the order of remaining entries in formContainer._fields.

@armaang1729 armaang1729 force-pushed the tableComponentFirstCheckIn branch from e878597 to 90ced91 Compare May 20, 2026 10:21
@github-actions github-actions Bot force-pushed the tableComponentFirstCheckIn branch from 90ced91 to 16d7af4 Compare May 20, 2026 10:21
@armaang1729 armaang1729 force-pushed the tableComponentFirstCheckIn branch from 16d7af4 to 3db51ce Compare May 20, 2026 10:26
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

1 similar comment
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

1 similar comment
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

@armaang1729 armaang1729 requested a review from devgurjar May 26, 2026 05:13
@github-actions github-actions Bot force-pushed the tableComponentFirstCheckIn branch from 99f95f1 to 02bb9c8 Compare June 15, 2026 08:43
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

1 similar comment
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

1 similar comment
@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

@adobe-bot

Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants