Problem/Motivation
There is no way to insert a new table row at a specific position. Rows can only be appended at the
end via the "Add Row" button. Editors who need to add content at the top or middle of a table must
manually copy/paste cell data downward to make room, which is error-prone and time-consuming for
large tables.
This is especially impactful for tables where newest information goes first (e.g., revision
histories, schedule updates), as every new entry requires shifting all existing rows.
This feature was developed at the VA CMS (
href="https://github.com/department-of-veterans-affairs/va.gov-cms">va.gov-cms) alongside
href="https://www.drupal.org/project/tablefield/issues/3341971">#3341971 (which disables
drag-and-drop to prevent metadata pollution of table data). With drag-and-drop disabled, there is no
way to reorder rows at all, making positional insert essential. However, this feature is
independently useful even with drag-and-drop enabled, since drag-and-drop can reorder existing rows
but cannot insert a new blank row at a specific position.
Steps to reproduce
1. Create or edit a node with a tablefield.
2. Populate several rows with data.
3. Attempt to add a new row between existing rows (e.g., before row 1).
4. The only option is "Add Row", which appends to the end. To place content between existing rows,
you must manually copy/paste cell values downward.
Proposed resolution
Add a hidden insert_index form value and a hidden AJAX trigger button to the tablefield
element. A small JavaScript behavior creates "+" buttons as hover overlays at each row boundary
(before the first row, between each pair of rows, and after the last row). Clicking a "+" button sets
the insert index and fires the hidden trigger.
The submit callback reads the index, uses array_splice to insert a blank row at that
position, re-keys the array to maintain clean 0-based numeric indices, increments the row count, and
writes the shifted data back to form state, reusing the existing submitCallbackRebuild
/ ajaxCallbackRebuild AJAX plumbing.
The patch adds:
src/Element/Tablefield.php- hidden insert_index field, hidden trigger button, and
new elseif branch in submitCallbackRebuildjs/tablefield-insertrow.js- Drupal behavior that creates and positions the "+"
hover overlayscss/tablefield-insertrow.css- styles for the hover zones and "+" buttonstablefield.libraries.yml- library definition for the above assets
No changes to the data model. Saved table values remain plain numeric arrays. No weight, spacer, or
insert_index metadata is persisted.
Remaining tasks
- Review and test the patch.
- Confirm AJAX behavior across different admin themes.
User interface changes
Hovering between table rows in the edit form reveals a blue line with a "+" button. Clicking it
inserts a blank row at that position via AJAX, shifting existing rows down. The controls are not
visible until hovered, so the editing experience is unchanged for users who do not need the feature.
API changes
None. The feature is gated behind the existing #addrow element property. No new form
element properties or hooks are introduced.
Data model changes
None. Saved table data remains the same plain numeric array structure.
Issue fork tablefield-3580596
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 #3
skyriter commentedI have reviewed the work done and can confirm that the patch from #2 is working.
Screenshot
Comment #4
skyriter commented